From 1d36df9df23b7383f024e516df7d2083127d069b Mon Sep 17 00:00:00 2001 From: Liang Guo Date: Fri, 1 Jul 2016 12:32:58 +0100 Subject: [PATCH 1/1] Import spice-gtk_0.32.orig.tar.bz2 [dgit import orig spice-gtk_0.32.orig.tar.bz2] --- .tarball-version | 1 + .version | 1 + AUTHORS | 6 + COPYING | 502 + ChangeLog | 13139 +++++++++ Makefile.am | 113 + Makefile.in | 1110 + NEWS | 414 + README | 56 + THANKS | 54 + TODO | 5 + aclocal.m4 | 2140 ++ build-aux/ar-lib | 270 + build-aux/compile | 347 + build-aux/config.guess | 1421 + build-aux/config.sub | 1807 ++ build-aux/depcomp | 791 + build-aux/git-version-gen | 158 + build-aux/install-sh | 501 + build-aux/ltmain.sh | 11147 ++++++++ build-aux/missing | 215 + build-aux/test-driver | 148 + config.h.in | 194 + configure | 23510 ++++++++++++++++ configure.ac | 648 + data/Makefile.am | 14 + data/Makefile.in | 648 + data/org.spice-space.lowlevelusbaccess.policy | 20 + data/spice-protocol.vapi | 210 + doc/Makefile.am | 3 + doc/Makefile.in | 743 + doc/reference/Makefile.am | 81 + doc/reference/Makefile.in | 927 + doc/reference/html/SpiceAudio.html | 273 + doc/reference/html/SpiceChannel.html | 962 + doc/reference/html/SpiceCursorChannel.html | 359 + doc/reference/html/SpiceDisplayChannel.html | 914 + doc/reference/html/SpiceFileTransferTask.html | 340 + doc/reference/html/SpiceInputsChannel.html | 614 + doc/reference/html/SpiceMainChannel.html | 1800 ++ doc/reference/html/SpicePlaybackChannel.html | 456 + doc/reference/html/SpicePortChannel.html | 461 + doc/reference/html/SpiceRecordChannel.html | 367 + doc/reference/html/SpiceSession.html | 1395 + doc/reference/html/SpiceSmartcardChannel.html | 130 + doc/reference/html/SpiceSmartcardManager.html | 607 + doc/reference/html/SpiceUsbDeviceManager.html | 1070 + doc/reference/html/SpiceUsbredirChannel.html | 119 + doc/reference/html/SpiceWebdavChannel.html | 126 + doc/reference/html/annotation-glossary.html | 67 + doc/reference/html/api-index-deprecated.html | 87 + doc/reference/html/api-index-full.html | 1195 + doc/reference/html/api-reference.html | 110 + doc/reference/html/application-support.html | 52 + doc/reference/html/ch01.html | 58 + doc/reference/html/ch02.html | 67 + doc/reference/html/ch03.html | 40 + doc/reference/html/home.png | Bin 0 -> 256 bytes doc/reference/html/index.html | 107 + doc/reference/html/left-insensitive.png | Bin 0 -> 395 bytes doc/reference/html/left.png | Bin 0 -> 262 bytes doc/reference/html/object-tree.html | 58 + doc/reference/html/right-insensitive.png | Bin 0 -> 373 bytes doc/reference/html/right.png | Bin 0 -> 261 bytes .../html/spice-gtk-SpiceDisplay.html | 617 + .../html/spice-gtk-SpiceGtkSession.html | 190 + doc/reference/html/spice-gtk-SpiceURI.html | 527 + .../html/spice-gtk-SpiceUsbDeviceWidget.html | 115 + doc/reference/html/spice-gtk-Utilities.html | 158 + .../html/spice-gtk-Version-Information.html | 149 + doc/reference/html/spice-gtk.devhelp2 | 402 + doc/reference/html/style.css | 479 + doc/reference/html/up-insensitive.png | Bin 0 -> 374 bytes doc/reference/html/up.png | Bin 0 -> 260 bytes doc/reference/spice-gtk-docs.xml | 83 + doc/reference/spice-gtk-overrides.txt | 0 doc/reference/spice-gtk-sections.txt | 527 + doc/reference/spice-gtk.types | 49 + gtk-doc.make | 304 + intltool-extract.in | 0 intltool-merge.in | 0 intltool-update.in | 0 m4/gtk-doc.m4 | 88 + m4/intltool.m4 | 212 + m4/ld-version.m4 | 34 + m4/libtool.m4 | 8372 ++++++ m4/ltoptions.m4 | 437 + m4/ltsugar.m4 | 124 + m4/ltversion.m4 | 23 + m4/lt~obsolete.m4 | 99 + m4/manywarnings.m4 | 274 + m4/spice-compile-warnings.m4 | 150 + m4/warnings.m4 | 79 + man/Makefile.am | 16 + man/Makefile.in | 656 + man/spice-client.1 | 301 + man/spice-client.pod | 195 + po/ChangeLog | 8 + po/LINGUAS | 2 + po/Makefile.in.in | 221 + po/POTFILES.in | 8 + po/POTFILES.skip | 2 + po/fr.po | 235 + spice-client-glib-2.0.pc.in | 13 + spice-client-gtk-3.0.pc.in | 12 + spice-common/COPYING | 502 + spice-common/Makefile.am | 28 + spice-common/Makefile.in | 872 + spice-common/aclocal.m4 | 1832 ++ spice-common/build-aux/ar-lib | 270 + spice-common/build-aux/compile | 347 + spice-common/build-aux/config.guess | 1421 + spice-common/build-aux/config.sub | 1807 ++ spice-common/build-aux/depcomp | 791 + spice-common/build-aux/install-sh | 501 + spice-common/build-aux/ltmain.sh | 11147 ++++++++ spice-common/build-aux/missing | 215 + spice-common/build-aux/test-driver | 148 + spice-common/common/Makefile.am | 141 + spice-common/common/Makefile.in | 828 + spice-common/common/backtrace.c | 132 + spice-common/common/backtrace.h | 34 + spice-common/common/bitops.h | 87 + spice-common/common/canvas_base.c | 3582 +++ spice-common/common/canvas_base.h | 322 + spice-common/common/canvas_utils.c | 318 + spice-common/common/canvas_utils.h | 78 + spice-common/common/client_demarshallers.h | 35 + spice-common/common/client_marshallers.h | 82 + spice-common/common/draw.h | 305 + spice-common/common/gdi_canvas.c | 1860 ++ spice-common/common/gdi_canvas.h | 44 + .../common/generated_client_demarshallers.c | 8206 ++++++ .../common/generated_client_demarshallers1.c | 5882 ++++ .../common/generated_client_marshallers.c | 494 + .../common/generated_client_marshallers1.c | 251 + .../common/generated_server_demarshallers.c | 2176 ++ .../common/generated_server_marshallers.c | 1939 ++ .../common/generated_server_marshallers.h | 121 + spice-common/common/lines.c | 3611 +++ spice-common/common/lines.h | 136 + spice-common/common/log.c | 190 + spice-common/common/log.h | 111 + spice-common/common/lz.c | 753 + spice-common/common/lz.h | 81 + spice-common/common/lz_common.h | 74 + spice-common/common/lz_compress_tmpl.c | 540 + spice-common/common/lz_config.h | 39 + spice-common/common/lz_decompress_tmpl.c | 343 + spice-common/common/macros.h | 55 + spice-common/common/marshaller.c | 650 + spice-common/common/marshaller.h | 75 + spice-common/common/mem.c | 296 + spice-common/common/mem.h | 159 + spice-common/common/messages.h | 662 + spice-common/common/pixman_utils.c | 1609 ++ spice-common/common/pixman_utils.h | 143 + spice-common/common/quic.c | 1676 ++ spice-common/common/quic.h | 70 + spice-common/common/quic_config.h | 44 + spice-common/common/quic_family_tmpl.c | 115 + spice-common/common/quic_rgb_tmpl.c | 765 + spice-common/common/quic_tmpl.c | 635 + spice-common/common/rect.h | 150 + spice-common/common/region.c | 901 + spice-common/common/region.h | 70 + spice-common/common/ring.h | 168 + spice-common/common/rop3.c | 646 + spice-common/common/rop3.h | 39 + spice-common/common/snd_codec.c | 400 + spice-common/common/snd_codec.h | 82 + spice-common/common/spice_common.h | 37 + spice-common/common/ssl_verify.c | 548 + spice-common/common/ssl_verify.h | 67 + spice-common/common/sw_canvas.c | 1323 + spice-common/common/sw_canvas.h | 59 + spice-common/common/verify.h | 245 + spice-common/config.h.in | 231 + spice-common/configure | 17656 ++++++++++++ spice-common/configure.ac | 62 + spice-common/m4/ax_python_module.m4 | 49 + spice-common/m4/libtool.m4 | 8372 ++++++ spice-common/m4/ltoptions.m4 | 437 + spice-common/m4/ltsugar.m4 | 124 + spice-common/m4/ltversion.m4 | 23 + spice-common/m4/lt~obsolete.m4 | 99 + spice-common/m4/spice-deps.m4 | 284 + spice-common/python_modules/Makefile.am | 16 + spice-common/python_modules/Makefile.in | 480 + spice-common/python_modules/__init__.py | 0 spice-common/python_modules/codegen.py | 380 + spice-common/python_modules/demarshal.py | 1274 + spice-common/python_modules/marshal.py | 420 + spice-common/python_modules/ptypes.py | 1138 + spice-common/python_modules/spice_parser.py | 163 + spice-common/spice.proto | 1414 + spice-common/spice1.proto | 943 + spice-common/spice_codegen.py | 275 + spice-common/tests/Makefile.am | 66 + spice-common/tests/Makefile.in | 1127 + .../tests/generated_test_marshallers.c | 58 + .../tests/generated_test_marshallers.h | 26 + spice-common/tests/test-logging.c | 406 + spice-common/tests/test-marshallers.c | 43 + spice-common/tests/test-marshallers.h | 11 + spice-common/tests/test-marshallers.proto | 10 + spice-controller.pc.in | 12 + src/Makefile.am | 656 + src/Makefile.in | 1981 ++ src/bio-gio.c | 113 + src/bio-gio.h | 30 + src/channel-base.c | 283 + src/channel-cursor.c | 528 + src/channel-cursor.h | 81 + src/channel-display-gst.c | 483 + src/channel-display-mjpeg.c | 323 + src/channel-display-priv.h | 146 + src/channel-display.c | 1855 ++ src/channel-display.h | 161 + src/channel-inputs.c | 603 + src/channel-inputs.h | 101 + src/channel-main.c | 3496 +++ src/channel-main.h | 116 + src/channel-playback-priv.h | 24 + src/channel-playback.c | 503 + src/channel-playback.h | 80 + src/channel-port.c | 361 + src/channel-port.h | 80 + src/channel-record.c | 479 + src/channel-record.h | 81 + src/channel-smartcard.c | 571 + src/channel-smartcard.h | 72 + src/channel-usbredir-priv.h | 74 + src/channel-usbredir.c | 796 + src/channel-usbredir.h | 75 + src/channel-webdav.c | 616 + src/channel-webdav.h | 72 + src/client_sw_canvas.c | 20 + src/client_sw_canvas.h | 25 + src/continuation.c | 102 + src/continuation.h | 61 + src/controller/Makefile.am | 101 + src/controller/Makefile.in | 948 + src/controller/controller.c | 2405 ++ src/controller/controller.vala | 286 + src/controller/controller.vala.stamp | 0 src/controller/custom.h | 22 + src/controller/custom.vapi | 28 + src/controller/dump.c | 115 + src/controller/foreign-menu.c | 1490 + src/controller/foreign-menu.vala | 197 + src/controller/gio-windows-2.0.vapi | 30 + src/controller/menu.c | 733 + src/controller/menu.vala | 108 + src/controller/namedpipe.c | 270 + src/controller/namedpipe.h | 59 + src/controller/namedpipeconnection.c | 245 + src/controller/namedpipeconnection.h | 56 + src/controller/namedpipelistener.c | 330 + src/controller/namedpipelistener.h | 70 + src/controller/spice-controller-listener.c | 159 + src/controller/spice-controller-listener.h | 47 + src/controller/spice-controller.h | 172 + src/controller/spice-foreign-menu-listener.c | 161 + src/controller/spice-foreign-menu-listener.h | 47 + src/controller/test.c | 289 + src/controller/util.c | 388 + src/controller/util.vala | 42 + src/controller/win32-util.c | 161 + src/controller/win32-util.h | 30 + src/coroutine.h | 83 + src/coroutine_gthread.c | 170 + src/coroutine_ucontext.c | 150 + src/coroutine_winfibers.c | 126 + src/decode-glz-tmpl.c | 336 + src/decode-glz.c | 474 + src/decode-jpeg.c | 191 + src/decode-zlib.c | 89 + src/decode.h | 44 + src/desktop-integration.c | 222 + src/desktop-integration.h | 64 + src/gio-coroutine.c | 275 + src/gio-coroutine.h | 66 + src/giopipe.c | 488 + src/giopipe.h | 29 + src/keymap-gen.pl | 214 + src/keymaps.csv | 490 + src/map-file | 151 + src/smartcard-manager-priv.h | 37 + src/smartcard-manager.c | 721 + src/smartcard-manager.h | 105 + src/spice-audio-priv.h | 42 + src/spice-audio.c | 274 + src/spice-audio.h | 113 + src/spice-channel-cache.h | 139 + src/spice-channel-enums.h | 7 + src/spice-channel-priv.h | 214 + src/spice-channel.c | 3085 ++ src/spice-channel.h | 152 + src/spice-client-glib-usb-acl-helper.c | 363 + src/spice-client-gtk-manual.defs | 117 + src/spice-client-gtk.h | 32 + src/spice-client-gtk.override | 171 + src/spice-client.c | 34 + src/spice-client.h | 98 + src/spice-cmdline.c | 98 + src/spice-cmdline.h | 29 + src/spice-common.h | 36 + src/spice-file-transfer-task.h | 50 + src/spice-glib-sym-file | 125 + src/spice-grabsequence-priv.h | 29 + src/spice-grabsequence.c | 171 + src/spice-grabsequence.h | 62 + src/spice-gstaudio.c | 715 + src/spice-gstaudio.h | 56 + src/spice-gtk-session-priv.h | 51 + src/spice-gtk-session.c | 1291 + src/spice-gtk-session.h | 47 + src/spice-gtk-sym-file | 21 + src/spice-marshal.txt | 15 + src/spice-option.c | 323 + src/spice-option.h | 35 + src/spice-pulse.c | 1307 + src/spice-pulse.h | 57 + src/spice-session-priv.h | 104 + src/spice-session.c | 2787 ++ src/spice-session.h | 120 + src/spice-types.h | 39 + src/spice-uri-priv.h | 30 + src/spice-uri.c | 529 + src/spice-uri.h | 68 + src/spice-util-priv.h | 38 + src/spice-util.c | 497 + src/spice-util.h | 63 + src/spice-version.h | 76 + src/spice-version.h.in | 76 + src/spice-widget-cairo.c | 137 + src/spice-widget-egl.c | 681 + src/spice-widget-priv.h | 171 + src/spice-widget.c | 2922 ++ src/spice-widget.h | 75 + src/spicy-connect.c | 248 + src/spicy-connect.h | 26 + src/spicy-screenshot.c | 194 + src/spicy-stats.c | 136 + src/spicy.c | 1930 ++ src/usb-acl-helper.c | 284 + src/usb-acl-helper.h | 72 + src/usb-device-manager-priv.h | 48 + src/usb-device-manager.c | 2266 ++ src/usb-device-manager.h | 148 + src/usb-device-widget.c | 614 + src/usb-device-widget.h | 50 + src/usbdk_api.c | 187 + src/usbdk_api.h | 34 + src/usbutil.c | 321 + src/usbutil.h | 39 + src/vmcstream.c | 523 + src/vmcstream.h | 81 + src/vncdisplaykeymap.c | 322 + src/vncdisplaykeymap.h | 36 + src/vncdisplaykeymap_osx2xtkbd.c | 117 + src/vncdisplaykeymap_win322xtkbd.c | 141 + src/vncdisplaykeymap_x112xtkbd.c | 132 + src/vncdisplaykeymap_xorgevdev2xtkbd.c | 240 + src/vncdisplaykeymap_xorgkbd2xtkbd.c | 112 + src/vncdisplaykeymap_xorgxquartz2xtkbd.c | 117 + src/vncdisplaykeymap_xorgxwin2xtkbd.c | 112 + src/win-usb-clerk.h | 36 + src/win-usb-dev.c | 583 + src/win-usb-dev.h | 110 + src/win-usb-driver-install.c | 421 + src/win-usb-driver-install.h | 106 + src/wocky-http-proxy.c | 520 + src/wocky-http-proxy.h | 54 + tests/Makefile.am | 45 + tests/Makefile.in | 1242 + tests/coroutine.c | 132 + tests/mock-acl-helper.c | 90 + tests/pipe.c | 525 + tests/session.c | 72 + tests/uri.c | 148 + tests/usb-acl-helper.c | 226 + tests/util.c | 208 + vapi/Makefile.am | 40 + vapi/Makefile.in | 670 + vapi/SpiceClientGLib-2.0.metadata | 1 + vapi/spice-client-glib-2.0.deps | 1 + vapi/spice-client-gtk-3.0.deps | 2 + 389 files changed, 248399 insertions(+) create mode 100644 .tarball-version create mode 100644 .version create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 THANKS create mode 100644 TODO create mode 100644 aclocal.m4 create mode 100755 build-aux/ar-lib create mode 100755 build-aux/compile create mode 100755 build-aux/config.guess create mode 100755 build-aux/config.sub create mode 100755 build-aux/depcomp create mode 100755 build-aux/git-version-gen create mode 100755 build-aux/install-sh create mode 100644 build-aux/ltmain.sh create mode 100755 build-aux/missing create mode 100755 build-aux/test-driver create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100644 data/Makefile.am create mode 100644 data/Makefile.in create mode 100644 data/org.spice-space.lowlevelusbaccess.policy create mode 100644 data/spice-protocol.vapi create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/reference/Makefile.am create mode 100644 doc/reference/Makefile.in create mode 100644 doc/reference/html/SpiceAudio.html create mode 100644 doc/reference/html/SpiceChannel.html create mode 100644 doc/reference/html/SpiceCursorChannel.html create mode 100644 doc/reference/html/SpiceDisplayChannel.html create mode 100644 doc/reference/html/SpiceFileTransferTask.html create mode 100644 doc/reference/html/SpiceInputsChannel.html create mode 100644 doc/reference/html/SpiceMainChannel.html create mode 100644 doc/reference/html/SpicePlaybackChannel.html create mode 100644 doc/reference/html/SpicePortChannel.html create mode 100644 doc/reference/html/SpiceRecordChannel.html create mode 100644 doc/reference/html/SpiceSession.html create mode 100644 doc/reference/html/SpiceSmartcardChannel.html create mode 100644 doc/reference/html/SpiceSmartcardManager.html create mode 100644 doc/reference/html/SpiceUsbDeviceManager.html create mode 100644 doc/reference/html/SpiceUsbredirChannel.html create mode 100644 doc/reference/html/SpiceWebdavChannel.html create mode 100644 doc/reference/html/annotation-glossary.html create mode 100644 doc/reference/html/api-index-deprecated.html create mode 100644 doc/reference/html/api-index-full.html create mode 100644 doc/reference/html/api-reference.html create mode 100644 doc/reference/html/application-support.html create mode 100644 doc/reference/html/ch01.html create mode 100644 doc/reference/html/ch02.html create mode 100644 doc/reference/html/ch03.html create mode 100644 doc/reference/html/home.png create mode 100644 doc/reference/html/index.html create mode 100644 doc/reference/html/left-insensitive.png create mode 100644 doc/reference/html/left.png create mode 100644 doc/reference/html/object-tree.html create mode 100644 doc/reference/html/right-insensitive.png create mode 100644 doc/reference/html/right.png create mode 100644 doc/reference/html/spice-gtk-SpiceDisplay.html create mode 100644 doc/reference/html/spice-gtk-SpiceGtkSession.html create mode 100644 doc/reference/html/spice-gtk-SpiceURI.html create mode 100644 doc/reference/html/spice-gtk-SpiceUsbDeviceWidget.html create mode 100644 doc/reference/html/spice-gtk-Utilities.html create mode 100644 doc/reference/html/spice-gtk-Version-Information.html create mode 100644 doc/reference/html/spice-gtk.devhelp2 create mode 100644 doc/reference/html/style.css create mode 100644 doc/reference/html/up-insensitive.png create mode 100644 doc/reference/html/up.png create mode 100644 doc/reference/spice-gtk-docs.xml create mode 100644 doc/reference/spice-gtk-overrides.txt create mode 100644 doc/reference/spice-gtk-sections.txt create mode 100644 doc/reference/spice-gtk.types create mode 100644 gtk-doc.make create mode 100644 intltool-extract.in create mode 100644 intltool-merge.in create mode 100644 intltool-update.in create mode 100644 m4/gtk-doc.m4 create mode 100644 m4/intltool.m4 create mode 100644 m4/ld-version.m4 create mode 100644 m4/libtool.m4 create mode 100644 m4/ltoptions.m4 create mode 100644 m4/ltsugar.m4 create mode 100644 m4/ltversion.m4 create mode 100644 m4/lt~obsolete.m4 create mode 100644 m4/manywarnings.m4 create mode 100644 m4/spice-compile-warnings.m4 create mode 100644 m4/warnings.m4 create mode 100644 man/Makefile.am create mode 100644 man/Makefile.in create mode 100644 man/spice-client.1 create mode 100644 man/spice-client.pod create mode 100644 po/ChangeLog create mode 100644 po/LINGUAS create mode 100644 po/Makefile.in.in create mode 100644 po/POTFILES.in create mode 100644 po/POTFILES.skip create mode 100644 po/fr.po create mode 100644 spice-client-glib-2.0.pc.in create mode 100644 spice-client-gtk-3.0.pc.in create mode 100644 spice-common/COPYING create mode 100644 spice-common/Makefile.am create mode 100644 spice-common/Makefile.in create mode 100644 spice-common/aclocal.m4 create mode 100755 spice-common/build-aux/ar-lib create mode 100755 spice-common/build-aux/compile create mode 100755 spice-common/build-aux/config.guess create mode 100755 spice-common/build-aux/config.sub create mode 100755 spice-common/build-aux/depcomp create mode 100755 spice-common/build-aux/install-sh create mode 100644 spice-common/build-aux/ltmain.sh create mode 100755 spice-common/build-aux/missing create mode 100755 spice-common/build-aux/test-driver create mode 100644 spice-common/common/Makefile.am create mode 100644 spice-common/common/Makefile.in create mode 100644 spice-common/common/backtrace.c create mode 100644 spice-common/common/backtrace.h create mode 100644 spice-common/common/bitops.h create mode 100644 spice-common/common/canvas_base.c create mode 100644 spice-common/common/canvas_base.h create mode 100644 spice-common/common/canvas_utils.c create mode 100644 spice-common/common/canvas_utils.h create mode 100644 spice-common/common/client_demarshallers.h create mode 100644 spice-common/common/client_marshallers.h create mode 100644 spice-common/common/draw.h create mode 100644 spice-common/common/gdi_canvas.c create mode 100644 spice-common/common/gdi_canvas.h create mode 100644 spice-common/common/generated_client_demarshallers.c create mode 100644 spice-common/common/generated_client_demarshallers1.c create mode 100644 spice-common/common/generated_client_marshallers.c create mode 100644 spice-common/common/generated_client_marshallers1.c create mode 100644 spice-common/common/generated_server_demarshallers.c create mode 100644 spice-common/common/generated_server_marshallers.c create mode 100644 spice-common/common/generated_server_marshallers.h create mode 100644 spice-common/common/lines.c create mode 100644 spice-common/common/lines.h create mode 100644 spice-common/common/log.c create mode 100644 spice-common/common/log.h create mode 100644 spice-common/common/lz.c create mode 100644 spice-common/common/lz.h create mode 100644 spice-common/common/lz_common.h create mode 100644 spice-common/common/lz_compress_tmpl.c create mode 100644 spice-common/common/lz_config.h create mode 100644 spice-common/common/lz_decompress_tmpl.c create mode 100644 spice-common/common/macros.h create mode 100644 spice-common/common/marshaller.c create mode 100644 spice-common/common/marshaller.h create mode 100644 spice-common/common/mem.c create mode 100644 spice-common/common/mem.h create mode 100644 spice-common/common/messages.h create mode 100644 spice-common/common/pixman_utils.c create mode 100644 spice-common/common/pixman_utils.h create mode 100644 spice-common/common/quic.c create mode 100644 spice-common/common/quic.h create mode 100644 spice-common/common/quic_config.h create mode 100644 spice-common/common/quic_family_tmpl.c create mode 100644 spice-common/common/quic_rgb_tmpl.c create mode 100644 spice-common/common/quic_tmpl.c create mode 100644 spice-common/common/rect.h create mode 100644 spice-common/common/region.c create mode 100644 spice-common/common/region.h create mode 100644 spice-common/common/ring.h create mode 100644 spice-common/common/rop3.c create mode 100644 spice-common/common/rop3.h create mode 100644 spice-common/common/snd_codec.c create mode 100644 spice-common/common/snd_codec.h create mode 100644 spice-common/common/spice_common.h create mode 100644 spice-common/common/ssl_verify.c create mode 100644 spice-common/common/ssl_verify.h create mode 100644 spice-common/common/sw_canvas.c create mode 100644 spice-common/common/sw_canvas.h create mode 100644 spice-common/common/verify.h create mode 100644 spice-common/config.h.in create mode 100755 spice-common/configure create mode 100644 spice-common/configure.ac create mode 100644 spice-common/m4/ax_python_module.m4 create mode 100644 spice-common/m4/libtool.m4 create mode 100644 spice-common/m4/ltoptions.m4 create mode 100644 spice-common/m4/ltsugar.m4 create mode 100644 spice-common/m4/ltversion.m4 create mode 100644 spice-common/m4/lt~obsolete.m4 create mode 100644 spice-common/m4/spice-deps.m4 create mode 100644 spice-common/python_modules/Makefile.am create mode 100644 spice-common/python_modules/Makefile.in create mode 100644 spice-common/python_modules/__init__.py create mode 100644 spice-common/python_modules/codegen.py create mode 100644 spice-common/python_modules/demarshal.py create mode 100644 spice-common/python_modules/marshal.py create mode 100644 spice-common/python_modules/ptypes.py create mode 100644 spice-common/python_modules/spice_parser.py create mode 100644 spice-common/spice.proto create mode 100644 spice-common/spice1.proto create mode 100755 spice-common/spice_codegen.py create mode 100644 spice-common/tests/Makefile.am create mode 100644 spice-common/tests/Makefile.in create mode 100644 spice-common/tests/generated_test_marshallers.c create mode 100644 spice-common/tests/generated_test_marshallers.h create mode 100644 spice-common/tests/test-logging.c create mode 100644 spice-common/tests/test-marshallers.c create mode 100644 spice-common/tests/test-marshallers.h create mode 100644 spice-common/tests/test-marshallers.proto create mode 100644 spice-controller.pc.in create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/bio-gio.c create mode 100644 src/bio-gio.h create mode 100644 src/channel-base.c create mode 100644 src/channel-cursor.c create mode 100644 src/channel-cursor.h create mode 100644 src/channel-display-gst.c create mode 100644 src/channel-display-mjpeg.c create mode 100644 src/channel-display-priv.h create mode 100644 src/channel-display.c create mode 100644 src/channel-display.h create mode 100644 src/channel-inputs.c create mode 100644 src/channel-inputs.h create mode 100644 src/channel-main.c create mode 100644 src/channel-main.h create mode 100644 src/channel-playback-priv.h create mode 100644 src/channel-playback.c create mode 100644 src/channel-playback.h create mode 100644 src/channel-port.c create mode 100644 src/channel-port.h create mode 100644 src/channel-record.c create mode 100644 src/channel-record.h create mode 100644 src/channel-smartcard.c create mode 100644 src/channel-smartcard.h create mode 100644 src/channel-usbredir-priv.h create mode 100644 src/channel-usbredir.c create mode 100644 src/channel-usbredir.h create mode 100644 src/channel-webdav.c create mode 100644 src/channel-webdav.h create mode 100644 src/client_sw_canvas.c create mode 100644 src/client_sw_canvas.h create mode 100644 src/continuation.c create mode 100644 src/continuation.h create mode 100644 src/controller/Makefile.am create mode 100644 src/controller/Makefile.in create mode 100644 src/controller/controller.c create mode 100644 src/controller/controller.vala create mode 100644 src/controller/controller.vala.stamp create mode 100644 src/controller/custom.h create mode 100644 src/controller/custom.vapi create mode 100644 src/controller/dump.c create mode 100644 src/controller/foreign-menu.c create mode 100644 src/controller/foreign-menu.vala create mode 100644 src/controller/gio-windows-2.0.vapi create mode 100644 src/controller/menu.c create mode 100644 src/controller/menu.vala create mode 100644 src/controller/namedpipe.c create mode 100644 src/controller/namedpipe.h create mode 100644 src/controller/namedpipeconnection.c create mode 100644 src/controller/namedpipeconnection.h create mode 100644 src/controller/namedpipelistener.c create mode 100644 src/controller/namedpipelistener.h create mode 100644 src/controller/spice-controller-listener.c create mode 100644 src/controller/spice-controller-listener.h create mode 100644 src/controller/spice-controller.h create mode 100644 src/controller/spice-foreign-menu-listener.c create mode 100644 src/controller/spice-foreign-menu-listener.h create mode 100644 src/controller/test.c create mode 100644 src/controller/util.c create mode 100644 src/controller/util.vala create mode 100644 src/controller/win32-util.c create mode 100644 src/controller/win32-util.h create mode 100644 src/coroutine.h create mode 100644 src/coroutine_gthread.c create mode 100644 src/coroutine_ucontext.c create mode 100644 src/coroutine_winfibers.c create mode 100644 src/decode-glz-tmpl.c create mode 100644 src/decode-glz.c create mode 100644 src/decode-jpeg.c create mode 100644 src/decode-zlib.c create mode 100644 src/decode.h create mode 100644 src/desktop-integration.c create mode 100644 src/desktop-integration.h create mode 100644 src/gio-coroutine.c create mode 100644 src/gio-coroutine.h create mode 100644 src/giopipe.c create mode 100644 src/giopipe.h create mode 100755 src/keymap-gen.pl create mode 100644 src/keymaps.csv create mode 100644 src/map-file create mode 100644 src/smartcard-manager-priv.h create mode 100644 src/smartcard-manager.c create mode 100644 src/smartcard-manager.h create mode 100644 src/spice-audio-priv.h create mode 100644 src/spice-audio.c create mode 100644 src/spice-audio.h create mode 100644 src/spice-channel-cache.h create mode 100644 src/spice-channel-enums.h create mode 100644 src/spice-channel-priv.h create mode 100644 src/spice-channel.c create mode 100644 src/spice-channel.h create mode 100644 src/spice-client-glib-usb-acl-helper.c create mode 100644 src/spice-client-gtk-manual.defs create mode 100644 src/spice-client-gtk.h create mode 100644 src/spice-client-gtk.override create mode 100644 src/spice-client.c create mode 100644 src/spice-client.h create mode 100644 src/spice-cmdline.c create mode 100644 src/spice-cmdline.h create mode 100644 src/spice-common.h create mode 100644 src/spice-file-transfer-task.h create mode 100644 src/spice-glib-sym-file create mode 100644 src/spice-grabsequence-priv.h create mode 100644 src/spice-grabsequence.c create mode 100644 src/spice-grabsequence.h create mode 100644 src/spice-gstaudio.c create mode 100644 src/spice-gstaudio.h create mode 100644 src/spice-gtk-session-priv.h create mode 100644 src/spice-gtk-session.c create mode 100644 src/spice-gtk-session.h create mode 100644 src/spice-gtk-sym-file create mode 100644 src/spice-marshal.txt create mode 100644 src/spice-option.c create mode 100644 src/spice-option.h create mode 100644 src/spice-pulse.c create mode 100644 src/spice-pulse.h create mode 100644 src/spice-session-priv.h create mode 100644 src/spice-session.c create mode 100644 src/spice-session.h create mode 100644 src/spice-types.h create mode 100644 src/spice-uri-priv.h create mode 100644 src/spice-uri.c create mode 100644 src/spice-uri.h create mode 100644 src/spice-util-priv.h create mode 100644 src/spice-util.c create mode 100644 src/spice-util.h create mode 100644 src/spice-version.h create mode 100644 src/spice-version.h.in create mode 100644 src/spice-widget-cairo.c create mode 100644 src/spice-widget-egl.c create mode 100644 src/spice-widget-priv.h create mode 100644 src/spice-widget.c create mode 100644 src/spice-widget.h create mode 100644 src/spicy-connect.c create mode 100644 src/spicy-connect.h create mode 100644 src/spicy-screenshot.c create mode 100644 src/spicy-stats.c create mode 100644 src/spicy.c create mode 100644 src/usb-acl-helper.c create mode 100644 src/usb-acl-helper.h create mode 100644 src/usb-device-manager-priv.h create mode 100644 src/usb-device-manager.c create mode 100644 src/usb-device-manager.h create mode 100644 src/usb-device-widget.c create mode 100644 src/usb-device-widget.h create mode 100644 src/usbdk_api.c create mode 100644 src/usbdk_api.h create mode 100644 src/usbutil.c create mode 100644 src/usbutil.h create mode 100644 src/vmcstream.c create mode 100644 src/vmcstream.h create mode 100644 src/vncdisplaykeymap.c create mode 100644 src/vncdisplaykeymap.h create mode 100644 src/vncdisplaykeymap_osx2xtkbd.c create mode 100644 src/vncdisplaykeymap_win322xtkbd.c create mode 100644 src/vncdisplaykeymap_x112xtkbd.c create mode 100644 src/vncdisplaykeymap_xorgevdev2xtkbd.c create mode 100644 src/vncdisplaykeymap_xorgkbd2xtkbd.c create mode 100644 src/vncdisplaykeymap_xorgxquartz2xtkbd.c create mode 100644 src/vncdisplaykeymap_xorgxwin2xtkbd.c create mode 100644 src/win-usb-clerk.h create mode 100644 src/win-usb-dev.c create mode 100644 src/win-usb-dev.h create mode 100644 src/win-usb-driver-install.c create mode 100644 src/win-usb-driver-install.h create mode 100644 src/wocky-http-proxy.c create mode 100644 src/wocky-http-proxy.h create mode 100644 tests/Makefile.am create mode 100644 tests/Makefile.in create mode 100644 tests/coroutine.c create mode 100644 tests/mock-acl-helper.c create mode 100644 tests/pipe.c create mode 100644 tests/session.c create mode 100644 tests/uri.c create mode 100644 tests/usb-acl-helper.c create mode 100644 tests/util.c create mode 100644 vapi/Makefile.am create mode 100644 vapi/Makefile.in create mode 100644 vapi/SpiceClientGLib-2.0.metadata create mode 100644 vapi/spice-client-glib-2.0.deps create mode 100644 vapi/spice-client-gtk-3.0.deps diff --git a/.tarball-version b/.tarball-version new file mode 100644 index 0000000..00d0c14 --- /dev/null +++ b/.tarball-version @@ -0,0 +1 @@ +0.32 diff --git a/.version b/.version new file mode 100644 index 0000000..00d0c14 --- /dev/null +++ b/.version @@ -0,0 +1 @@ +0.32 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..5c0c4d6 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +The following people contributed significantly to spice-gtk: + +Gerd Hoffmann - original author +Marc-André Lureau - maintainer +Hans de Goede - usb redirection +Christophe Fergeau - smartcard diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..5af797e --- /dev/null +++ b/ChangeLog @@ -0,0 +1,13139 @@ +2016-06-21 Marc-André Lureau + + Update NEWS for 0.32 release + +2016-06-21 Pavel Grunt + + session: Keep brackets around ipv6 hostname + According to rfc2732: + "To use a literal IPv6 address in a URL, the literal address should be + enclosed in "[" and "]" characters." + + Resolves: rhbz#1331777 + + Acked-by: Marc-André Lureau + + session: Removed write-only variable + Acked-by: Marc-André Lureau + +2016-06-21 Marc-André Lureau + + mailmap: fix my name + +2016-06-21 Victor Toso + + main: channel-main to increase file-transfer reference + This is a minor fix in the logic as in both situations (with or + without the patch) the reference count for the SpiceFileTransferTask + object is the same. + + The change is interesting as SpiceFileTransferTask is created but on + g_file_read_async() it increases its reference count while + c->file_xfer_tasks keeps the original one. + + It should be the other way around. + Acked-by: Marc-André Lureau + + main: assign variable after check for null + Acked-by: Pavel Grunt + +2016-06-20 Christophe Fergeau + + build: Fix _DEPENDENCIES use + We want to trigger rebuild of libspice-client-gtk-3.0.la or + libspice-client-glib-2.0.la whenever the corresponding symbol file + changes. + However _DEPENDENCIES is not the right way of handling that as it will + disable automatic automake dependency generation. + This was not causing issues mainly because _DEPENDENCIES was mispelt as + _DEPEDENCIES. + + Quoting automake manual: + https://www.gnu.org/software/automake/manual/automake.html#index-EXTRA_005fmaude_005fDEPENDENCIES-1 + « The EXTRA_*_DEPENDENCIES variable may be useful for cases where you + merely want to augment the automake-generated _DEPENDENCIES variable + rather than replacing it. » + + So this commit switches to use EXTRA_*_DEPENDENCIES rather than + *_DEPENDENCIES. + +2016-06-20 Marc-André Lureau + + build-sys: fix win32 build + Commit 0fafbe3 broke the build on win32, because it accesses + d->egl.enabled. Add a helper function and fix the build. + + Reported-by: Frediano Ziglio + Acked-by: Frediano Ziglio + + vncdisplaykeymap: fix -Werror=tautological-compare + vncdisplaykeymap.c: In function 'vnc_display_keymap_gdk2xtkbd_table': + vncdisplaykeymap.c:223:14: error: self-comparison always evaluates to true [-Werror=tautological-compare] + if (GDK_IS_WIN32_WINDOW(window)) { + + Acked-by: Frediano Ziglio + +2016-06-20 Marc-André Lureau + + widget: fix keyboard ungrab after click + Since the switch to a container widget (gtkstack then gtkeventbox), the + grab may be lost when clicking on the display. Since events are treated + at the top level container, set widget "above-child" to trap all of them + to solve this. + + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=96595 + + Reported-by: Frediano Ziglio + Tested-by: Frediano Ziglio + Acked-by: Fabiano Fidêncio + +2016-06-20 Marc-André Lureau + + widget: use scanout offset when using virgl + Ignoring the display area offset doesn't work nicely with virgl. Imho, + this condition is wrong even in QXL case. + +2016-06-17 Alexandru Visarion + + channel-main: Fix spice_main_file_copy_async annotation + Without (array zero-terminated=1), one null terminated array + parameter is translated into a single element, so its binding + isn't usable. + + Acked-by: Pavel Grunt + +2016-06-16 Frediano Ziglio + + widget: Disable IME context on display widget + This prevent Windows to handle IME on the widget which cause the + application to not receive keyboard events. + + To test this issue set keyboard layout to Japanese and Microsoft + IME (the default one). Set the input method to full katakana, assure + your remote-viewer is using this method and start pressing + alphabetical keys. On the guest (open a terminal, an editor or + a word processor to make easier) you won't see any character. + + Acked-by: Christophe Fergeau + +2016-06-15 Christophe Fergeau + + main: Don't delay update_display_timer(0) for up to 1 second + When using remote-viewer --full-screen with a VM/client with multiple + monitors, a race can be observed during auto-configuration. First, the + client monitors config is sent to the guest: + (remote-viewer:19480): GSpice-DEBUG: channel-main.c:1166 main-1:0: sending new monitors config to guest + (remote-viewer:19480): GSpice-DEBUG: channel-main.c:1183 main-1:0: monitor #0: 1920x1080+0+0 @ 32 bpp + (remote-viewer:19480): GSpice-DEBUG: channel-main.c:1183 main-1:0: monitor #1: 1920x1080+1920+0 @ 32 bpp + + Then we receive messages from the agent which trigger a call to + update_display_timer(0) + + This should cause the current monitors state to be sent to the server + very soon after this call. However, in the racy case, this is delayed + for nearly a second, and timer_set_display() ends up being called at the + wrong time, when information about the first display channel have been + received from the server, but not the second one. + + When this happens, we inform the server that only one monitor is active, + then the server sends a MonitorsConfig message with 2 monitors (first + request we sent), and then with just 1 monitor (second request we sent). + + This causes remote-viewer to show one fullscreen black window indicating + "Connected to server" on one monitor and a working fullscreen window on + the second monitor. + + update_display_timer(0) schedules a timeout to be run with + g_timeout_add_seconds(0). However, g_timeout_add_seconds() schedules + timers with a granularity of a second, so the timeout we scheduled with + g_timeout_add_seconds() may fire up to 1 second later than when we + called it, while we really wanted it to fire as soon as possible. + Special-casing update_display_timer(0) and using g_timeout_add() in that + case avoid this issue. In theory, the race could probably still happen + with a very very bad timing, but in practice I don't think it will be + possible to trigger it after this change. + + https://bugzilla.redhat.com/show_bug.cgi?id=1323092 + +2016-06-15 Alexander Bokovoy + + sasl: fix SASL GSSAPI by allowing NULL username + SASL GSSAPI module will try to negotiate authentication based on the + credentials in the default credentials cache. It does not matter if + SPICE knows username or not as SASL negotiation will pass through the + discovered name from the GSSAPI module. + + Acked-by: Fabiano Fidêncio + +2016-06-13 Frediano Ziglio + + Remove some warnings compiling for Windows + GetLastError returns a DWORD which is a "unsigned long" on Windows + so use "%lu" formatting instead of "%u". + + Acked-by: Marc-André Lureau + +2016-06-13 Pavel Grunt + + channel-display: Remove deprecated init functions + They are called at the construct time since spice-common commit: + 5b6be16b37370bb774aa3c2a7d5c41791fdc3a1e + + tests-uri: Define g_assert_nonnull + It is available since Glib 2.40 + + Require gtk+ 3.12 + Allow to use gtk_stack_get_child_by_name + +2016-06-13 Frediano Ziglio + + widget: Do not mix function linkage + This prevents a possible crash on windows 32 bit. + The linkage of UnhookWindowsHookEx is WINAPI which is __stdcall while + callback for g_clear_pointer is C. This could cause stack pointer + corruption depending on compiler flags. + On __stdcall linkage function change the stack pointer while returning + from a function removing the parameters. On C linkage function leave + the stack pointer unchanged. So if the compiler call a __stdcall + function as a C function it expect the stack pointer to be unchanged + causing the pointer to be inconsistent by an offset. + +2016-06-09 Frediano Ziglio + + widget: Do not ignore unsupported keys from keyboard + If Windows layout does not support a given key the resulting virtual code + is set to 0xFF. To avoid losing this raw key (causing the key not been + sent to remote machine) detect this condition and handle the key. + The check for raw scancode is there to understand if we can handle + correctly the key in following code. + This problem can happen for instance using a 106 key Japanese keyboard + while the layout is set in English; in this case keys like CONVERT not + forwarded correctly. + + Some note on how to reproduce and test this problem. + + Physical way: + 1- get a 106 key Japanese keyboard for your Windows client machine; + 2- setup your client to English keyboard layout; + 3- connect to a Linux machine (no matter the distro or version or + keyboard configuration); + 4- open "xinput test-xi2 " command on Linux (device is + the "AT" device in this case); + 5- press CONVERT or other keys not present on an English keyboard. + + Virtual way (Windows machine on a VM): + - set machine remote to VNC; + - assure Qmeu has lock-key-sync=off option to vnc; + - connect to Windows machine with a VNC client (I suggest TigerVNC + as remote-viewer do some keyboard insertion); + - do steps 2, 3, 4 above + - press the CONVERT key. If you don't have you can simulate, either + - change VNC client code to insert scancode 0x70 instead of another + key and press this key; + - disconnect main VNC client and use some tool to inject keys + (I use a modifier version of vncdotool). + + Acked-by: Christophe Fergeau + +2016-06-06 Francois Gouget + + streaming: Use the frame dimensions reported by the video decoder + The dimensions sent by the remote end are redundant and should not be + trusted. + + Acked-by: Pavel Grunt + +2016-06-06 Pavel Grunt + + widget: Avoid using GDK_GRAB_FAILED defined in Gtk 3.16. + The returned value from do_pointer_grab() is treated as a boolean - grab + was successful or not. Change the function to return a boolean value. + + Reported-by: Eduardo Lima (Etrunko) + Acked-by: Eduardo Lima (Etrunko) + + mingw: Fix -Werror format & missing-prototypes + -Wmissing prototypes were enabled in d5e3a4a5c34fc4408298e824872c4ed511b4bb3c + format warnings were added in da8ecf1f95382e8c12fd14915f471a3e76e4b178 + +2016-06-03 Pavel Grunt + + spicy: Do not show underscore in label + Acked-by: Eduardo Lima (Etrunko) + +2016-06-02 Pavel Grunt + + spice-uri: Add ipv6 support + Just basic support - http://user:password@[host]:port + + Resolves: rhbz#1335239 + + spice-uri: Validate uri scheme + Related: rhbz#1335239 + + Acked-by: Victor Toso + + spice-uri: Check if port is in allowed range + Use g_ascii_strtoll because it helps to detect overflow. + + Related: rhbz#1335239 + + Acked-by: Victor Toso + + spice-uri: Do not allow empty port string + Related: rhbz#1335239 + + Acked-by: Victor Toso + + spice-uri: Reset SpiceURI before parsing + Avoid using old values after parsing a new uri. + + Related: rhbz#1335239 + + tests: Add test for SpiceURI + Related: rhbz#1335239 + +2016-06-01 Francois Gouget + + streaming: Tweak the GStreamer decoder to avoid a compiler warning + We check that there is a matching frame in the queue before popping the + old ones. So we know the inner loop will find a match and thus that + frame will not be NULL. But figuring that out is too hard for the + compiler. + + Acked-by: Pavel Grunt + Reported-by: Marc-André Lureau + +2016-06-01 Marc-André Lureau + + build-sys: update manywarnings.m4 + Acked-by: Pavel Grunt + + build-sys: -Wshift-overflow=2 + manywarnings.m4 update will bring new flags that fail with some + glib/gst headers. + + Acked-by: Pavel Grunt + + Fix many -Werror=format warnings + Acked-by: Pavel Grunt + + build-sys: remove -Wmissing-declarations + The warning doesn't show up anymore. + + Acked-by: Pavel Grunt + +2016-06-01 Victor Toso + + channel: avoid crash on spice_channel_wakeup due NULL channel + Acked-by: Pavel Grunt + + tests: fix build with smartcard enabled + In file included from + ../spice-common/common/client_marshallers.h:29:0, + from ../src/spice-channel-priv.h:35, + from ../src/spice-file-transfer-task-priv.h:28, + from file-transfer.c:3: + ../spice-common/common/messages.h:45:23: fatal error: libcacard.h: No such file or directory + compilation terminated. + + Acked-by: Pavel Grunt + +2016-05-31 Marc-André Lureau + + doc: fix unused declarations + Fix all the gtk-doc: "unused declarations. They should be added to + spice-gtk-sections.txt in the appropriate place." + + doc: add some missing block comments + + Fix non gtk-doc comments + Fixes the following warning: + ../../src/vmcstream.c:124: warning: Symbol name not found at the start of the comment block. + ../../src/win-usb-driver-install.c:347: warning: Symbol name not found at the start of the comment block. + + build-sys: remove some gtk+ 2.0 warnings flags + As we dropped gtk+ 2.0 anyway. + + build-sys: enable -Wmissing-prototypes + Turns out it is possible to fix the warnings now. + +2016-05-31 Pavel Grunt + + Update README + Remove gtk2 related stuff. + Recommend dnf for installing dependencies. + + spice-uri: Mark parameter as unused + Acked-by: Victor Toso + +2016-05-28 Marc-André Lureau + + main: remove unneeded gtk-doc comments + They are no longer in the doc, and not really useful anyway + + main: remove SpiceFileTransferTaskPrivate + The struct is already private + +2016-05-27 Victor Toso + + file-xfer: make handle_status agnostic of channel-main + This make possible to rename the function to + spice_file_transfer_task_handle_status as a handler for + VDAgentFileXferStatusMessage for a specific task. + + This change is related to split SpiceFileTransferTask from + channel-main. + + Acked-by: Pavel Grunt + Acked-by: Jonathon Jongsma + +2016-05-25 Francois Gouget + + streaming: Constify the video stream's dest and clip parameters + They are only supposed to be changed when receiving the relevant server + message. + + Acked-by: Pavel Grunt + +2016-05-25 Pavel Grunt + + file-transfer-task: Hide internals of SpiceFileTransferTask + Acked-by: Fabiano Fidêncio + + file-trasfer-task: Protect header include + As stated in the commit d2f33178c40ac51b1c8b1bf796a328631d9869c7 Glib + applications should only include "spice-client.h". + + Acked-by: Fabiano Fidêncio + +2016-05-25 Marc-André Lureau + + egl: fix delayed widget realize + When the display is not yet realized, spice_display_widget_gl_scanout() + will fail because the egl context is not ready. The display is never + marked ready because the egl.image (and egl.scanout) is not set, and + some clients, such as virt-viewer will not realize the widget until the + display is ready. + + Deal with gl scanout updates when the widget is not yet realized, and + mark the display as ready when egl is enabled (when last display draw + signal is from gl). + + Acked-by: Pavel Grunt + + gtk: remove unneeded check + spice_cairo_draw_event() can deal with d->canvas.surface == NULL. + + Acked-by: Pavel Grunt + + gtk: rename spicex_* functions + spice-gtk used to have x11/shm backend, now it's only cairo + + Acked-by: Pavel Grunt + + gtk: move canvas related data in its own structure + Group canvas related data to a sub-structure. + + Acked-by: Pavel Grunt + + egl: bind the scanout texture + glEGLImageTargetTexture2DOES() changes the current bound texture. If + the last texture bound is the cursor, update_scanout() will modify the + cursor texture, instead of the display. + + Fix regression from commit 3539ac6212d506128bd38aad032e0363e78cb4f6. + + Acked-by: Pavel Grunt + + display: lower to debug gstreamer codec support + Acked-by: Pavel Grunt + +2016-05-25 Pavel Grunt + + spice-widget: Use correct enum value + GDK_GRAB_BROKEN is not GdkGrabStatus value, but GdkEventType + +2016-05-24 Pavel Grunt + + Update spice-common submodule + Fixes lz decompression crash: + https://bugzilla.redhat.com/show_bug.cgi?id=1285469 + + Christophe Fergeau (5): + Remove 2 unused vfuncs from client_marshallers.h + tests: Fix glib version check + log: Clamp SPICE_DEBUG_LEVEL if it's too high + log: Use SPICE_CONSTRUCTOR_FUNC + log: Make sure glib threading is initialized + + Eduardo Lima (Etrunko) (2): + Fix build in systems with Glib version older than 2.38 + 2/2] Add check for openssl + + Fabiano Fidêncio (7): + coverity: avoid use after free + coverity: avoid resource leak + coverity: avoid dereference after null check + coverity: avoid division or modulo by zero + coverity: remove unused value + coverity: remove structurally dead code + Use g_getenv() instead of getenv() + + Frediano Ziglio (6): + Cap logging level to the valid bounds + tests: exit on SIGABRT + define SPICE_CONSTRUCTOR_FUNC and SPICE_DESTRUCTOR_FUNC macros + use macro to define constructor function + fix 16 bpp LZ image decompression + Explicitly specify size of SpiceMsgSmartcardData + + Lin Ma (1): + build-sys: Define opengl GL_LIBS and GL_CFLAGS in generated Makefile.in + + Pavel Grunt (3): + Define canvas_fix_alignment when is used + test-logging: Include stdlib.h for _Exit() + Remove GL support + + Update .mailmap + +2016-05-23 Marc-André Lureau + + egl: set current context, fix multiple display + On X11, each widget has its own context. Make sure we are using the + widget associated context when using gl. + + With gtk 3.16, glEGLImageTargetTexture2DOES() can be called during + update scanout, since we can call gtk_gl_area_make_current(). On < 3.16, + do it before drawing. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1337721 + + Acked-by: Pavel Grunt + Acked-by: Victor Toso + + egl: don't terminate display + This is global to the display connection: all egl resources will be + released, including those from other widgets or from the application. + + Fix spice/virgl display being rendered black after another widget + display is destroyed. + + Acked-by: Pavel Grunt + Acked-by: Victor Toso + + egl: don't destroy wayland egl context + The egl context is from Gtk on Wayland. Destroy it only on X11. + + Acked-by: Pavel Grunt + Acked-by: Victor Toso + + egl: only swap buffers on x11 + Gtk does it for us already with GtkGlArea. + + Acked-by: Pavel Grunt + + channel: check if channel has a session + Since 8943d2329, the channel may be disconnected from the session + before it's destroyed. In this case, session is NULL. + + Fixes some critical with virt-manager when closing a display: + + (virt-manager:20451): GSpice-CRITICAL **: spice_session_is_for_migration: assertion 'SPICE_IS_SESSION(session)' failed + + Acked-by: Pavel Grunt + + util: remove STATIC_MUTEX macros + They are no longer needed since 0a9ec4ec0. + + Acked-by: Frediano Ziglio + +2016-05-19 Frediano Ziglio + + Spice-widget: Use new gdk_event_get_scancode if available + This new Gdk API allows in Windows to retrieve the raw scancodes sent + by Windows. + This allows us to do some translations getting the right value without + many hacks and supporting all possible layouts. + Windows convert the scancodes into virtual key codes. The translation is + 1 -> N based on different condition. Also a single virtual key code can + be originated from different scancodes. This make quite complicated + (if not impossible) to get the original scancode from the hardware_keycode + field (which in Windows is the virtual key). + The additional check for native_scancode after calling this function + allows to support key injection. + + Acked-by: Pavel Grunt + +2016-05-18 Francois Gouget + + streaming: Use decodebin as a fallback for the GStreamer video decoder + This means future video codecs may be supported automatically. + One can also force usage of decodebin by setting $SPICE_GSTVIDEO_AUTO. + + Acked-by: Pavel Grunt + + streaming: Probe GStreamer before advertising support for a codec + Acked-by: Pavel Grunt + + streaming: Allow disabling support for the builtin MJPEG video decoder + This makes it possible to test the GStreamer video decoder with MJPEG + streams. + + Acked-by: Pavel Grunt + + streaming: Add a GStreamer video decoder for MJPEG, VP8 and h264 + Acked-by: Pavel Grunt + + streaming: Let the video decoder queue, schedule and drop the frames + Acked-by: Pavel Grunt + +2016-05-16 Victor Toso + + file-xfer: fix segfault on agent disconnection + We are checking self->priv->error but accessing the argument GError * + which is NULL and leads to a segfault. + + Program received signal SIGSEGV, Segmentation fault. + spice_file_transfer_task_completed (self=self@entry=0x7fffd0006f00, error=0x0) at channel-main.c:2963 + 2963 VDAgentFileXferStatusMessage msg = { + (gdb) bt + #0 spice_file_transfer_task_completed (self=self@entry=0x7fffd0006f00, error=0x0) at channel-main.c:2963 + #1 in file_xfer_data_flushed_cb (source_object=0x7cc1d0, res=0x953390, user_data=user_data@entry=0x7fffd0006f00) at channel-main.c:1857 + #2 in g_task_return_now (task=0x953390) at gtask.c:1108 + #3 in g_task_return (task=0x953390, type=) at gtask.c:1166 + #4 in flush_foreach_remove (key=, value=, user_data=) at channel-main.c:928 + #5 in g_hash_table_foreach_remove_or_steal (hash_table=0x70cea0, func=func@entry=0x7ffff5616f10 , user_data=user_data@entry=0x0, notify=notify@entry=1) at ghash.c:1492 + #6 in g_hash_table_foreach_remove (hash_table=, func=func@entry=0x7ffff5616f10 , user_data=user_data@entry=0x0) at ghash.c:1538 + #7 in file_xfer_flushed (success=0, channel=0x7cc1d0) at channel-main.c:936 + #8 spice_main_channel_reset_agent (channel=0x7cc1d0) at channel-main.c:466 + #9 set_agent_connected (channel=0x7cc1d0, connected=connected@entry=0) at channel-main.c:1572 + #10 in spice_main_channel_reset (channel=0x7cc1d0, migrating=0) at channel-main.c:485 + #11 in spice_channel_coroutine (data=0x7cc1d0) at spice-channel.c:2564 + #12 in coroutine_trampoline (cc=0x7cb860) at coroutine_ucontext.c:63 + #13 in continuation_trampoline (i0=, i1=) at continuation.c:55 + #14 in ?? () from /lib64/libc.so.6 + #15 in ?? () + #16 in ?? () + Backtrace stopped: Cannot access memory at address + + Acked-by: Fabiano Fidêncio + +2016-05-13 Victor Toso + + file-xfer: fix file path leak + Acked-by: Fabiano Fidêncio + +2016-05-13 Pavel Grunt + + doc, gir: Clarify availability of skip spice_get_option_group + Commit c288627110bbec1aba48b0bf91ce7ab4b12f70b3 made the function + available for other languages through gobject introspections. Mention + the change in the function description. + Acked-by: Victor Toso + +2016-05-12 Pavel Grunt + + spicy: Add option to control syncing modifiers + Acked-by: Frediano Ziglio + + spice-gtk-session: Add sync modifiers property + It will help in cases where syncing modifiers keys is complicated: + * not working leds for modifiers keys + * different keyboard layout on the guest side + Acked-by: Frediano Ziglio + +2016-05-10 Victor Toso + + spicy: fix leak of transfer hash table + 184 (88 direct, 96 indirect) bytes in 1 blocks are definitely lost in + loss record 10,025 of 11,515 at 0x4C28BF6: malloc + (vg_replace_malloc.c:299) + by 0x9D33218: g_malloc (gmem.c:94) + by 0x9D49D02: g_slice_alloc (gslice.c:1025) + by 0x9D1CCBD: g_hash_table_new_full (ghash.c:711) + by 0x406196: connection_new (spicy.c:1693) + by 0x405BFE: main (spicy.c:1852) + + Acked-by: Christophe Fergeau + +2016-05-10 Marc-André Lureau + + spicy: add toggle mouse mode menu + This is just for testing, the UI could be different in better clients. + + Acked-by: Victor Toso + + main: do not always request client mouse mode + Whenever the mouse mode changed on the server, spice-gtk was requesting + client mode. Instead keep the last requested mode and request it + whenever it's possible. + + Reviewed-by: Victor Toso + + gtk: add spice_main_request_mouse_mode() + Send a SpiceMsgcMainMouseModeRequest message to request a mouse mode. + + This allows to switch between client/absolute and server/relative mouse + modes. + + This is necessary for some applications that require pointer + re-positioning, which we can't provide through a remote protocol easily + with client pointer (no such hardware-level message exists afaik). + + Reviewed-by: Victor Toso + +2016-05-09 Francois Gouget + + streaming: Rename num_drops_on_receive to arrive_late_count + The frame may not get dropped once that's left up to video decoders. + + Acked-by: Pavel Grunt + + streaming: Optimize handling of the decoded frame buffer + The MJPEG decoder does not need a zero-filled buffer. + + Acked-by: Pavel Grunt + + streaming: Enable adding alternative video decoders + This replaces the original channel-display-mjpeg API with a VideoDecoder + base class which can be reimplemented by other decoders. + Furthermore this moves the MJPEG-specific state information from the + display_stream struct to a derived class of VideoDecoder. + + Acked-by: Pavel Grunt + +2016-05-04 Visarion-Mingopol Alexandru + + doc,gir: Don't skip spice_get_option_group() + There is no reason to not include the spice_get_option_group + method in the generated bindings, as it can be useful. + + It was removed in the commit 2db9b8dd037e22d2b04e8e2aeecfd685524b7fef, + for the reason of causing warnings, but no warnings show up now. + + Acked-by: Fabiano Fidêncio + +2016-05-04 Marc-André Lureau + + gtk: fix server-mode mouse + Since switching to gtkstack, server-side mouse mode has some issues with + grabs. There seems to be some grab gtk+ issue, but it seems to fall + under the API user responsability to have its own window when dealing + with pointer grabs. And gtk+ commit 9d0e8401c (Turn stack into no-window + widget) made things worse. + + Making the widget an eventbox solves the grab issue. + + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=94764 + + Acked-by: Pavel Grunt + +2016-05-03 Victor Toso + + spice-channel: fix small leak + 182 bytes in 1 blocks are definitely lost in loss record 9,048 of 9,889 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0xB5F4270: g_malloc0 (gmem.c:124) + by 0x7320678: spice_channel_recv_link_hdr (spice-channel.c:1312) + by 0x7320678: spice_channel_coroutine (spice-channel.c:2543) + by 0x7355A4E: coroutine_trampoline (coroutine_ucontext.c:63) + by 0x7355802: continuation_trampoline (continuation.c:55) + + Acked-by: Christophe Fergeau + + spicevmc: don't disconnect on "cancel" + spicevmc was designed so its _finish functions should always be called; + With the gtask integration both _finish functions are trying to + disconnect the GCancellable even in the 'cancel' context which leads to + a deadlock as explained in the documentation. + + Resolves: https://bugs.freedesktop.org/show_bug.cgi?id=95032 + Acked-by: Jonathon Jongsma + +2016-05-02 Pavel Grunt + + channel: Abort migration in delayed unref + When channel is unref'ed during migration migrate_channel_event_cb + is called causing a crash by coroutine yielding to nonexistent channel. + + The delayed_unref happens for the target host channel and will only occur + when the migration process fails. + + As comment in spice_channel_coroutine says: + Co-routine exits now - the SpiceChannel object may no longer exist, + so don't do anything else now unless you like SEGVs + + Related: rhbz#1318574 + Acked-by: Victor Toso + + Do not use deprecated GtkStock + Use labels or named icons + + Deprecated since Gtk 3.10 + Acked-by: Victor Toso + +2016-05-02 Fabiano Fidêncio + + coverity: identical code for different branches + Acked-by: Victor Toso + + coverity: avoid out of bounds access + Acked-by: Victor Toso + +2016-04-27 Pavel Grunt + + channel-main: Use CHANNEL_DEBUG for migration events + To show which channel got an error or an unhandled event + Acked-by: Victor Toso + +2016-04-22 Javier Celaya + + Spice-widget: Allow smaller widget with scaling enabled + When resize-guest-to-match-window-size is disabled, the size request + (minimum size) of the spice widget is set to the current guest + resolution. The client window cannot be made smaller, even with + scale-display enabled. + + This patch sets a size request of 640x480 when either + resize-guest-to-match-window-size OR scale-display are enabled, making + it posible to shrink the window and scale down the display. + + Acked-by: Pavel Grunt + +2016-04-18 Takao Fujiwara + + Send Hangul key in KR keyboard + Korean keyboard assigns Hangul key on the position of Right Alt and + Left Alt and Hangul keys have the different scancodes but MapVirtualKey() + returned the same scancode and could not use Hangul key on Linux desktop. + + The fix is to send the right scancode of VK_HANGUL. + + Send key release event for some keys in JP keyboard + With the previous fix, WM_KEYDOWN of Alt+Zenkaku_Hankaku (VK_KANJI) can + be sent with spice-gtk but Alt+Zenkaku_Hankaku does not send the WM_KEYUP + event in Windows and it caused Linux desktop freeze with unlimited key + press events. + + The proposed fix is to send the key release event in spice-gtk. + + VK_DBE_ALPHANUMERIC, VK_DBE_HIRAGANA, VK_DBE_ROMAN are applied the + similar fixes. + + Send Zenkaku_Hankaku key in JP keyboard + Zenkaku_Hankaku key has the different virtual-key codes between WM_KEYDOWN + and WM_KEYUP and MapVirtualKey() cannot get the scancode from virtual-key + code of WM_KEYDOWN (VK_DBE_DBCSCHAR) and spice-gtk didn't send the key + press events and caused the desktop freeze with unlimited key release + events. + + The fix is to get the scancode from virtual-key code of WM_KEYUP + (VK_DBE_SBCSCHAR) and Zenkaku_Hankaku key works fine. + + Alt + Zenkaku_Hankaku key also has the different virtual-key code and + MapVirtualKey() cannot get the scancode from the virtual-key and + spice-gtk didn't send the key press events and Alt+Zenkaku_Hankaku + could not be used. + + The fix is to get the scancode from virtual-key code of Zenkaku_Hankaku key + (VK_DBE_SBCSCHAR). + + VK_CAPITAL, VK_DBE_ROMAN are also applied the similar fixes. + +2016-04-15 Pavel Grunt + + channel-main: Move variable to block where is needed + + channel-main: Add helper function for getting audio + Avoid repeating the same code and having a SpiceSession variable + defined when is not really needed. + Acked-by: Christophe Fergeau + +2016-04-08 Jonathon Jongsma + + Ensure that file transfers get cancelled + When canceling a file transfer task in spicy, the client would often + stop sending additional data, but it would not send a "CANCELLED" + message to the guest. Because of this, the partial file would remain in + the guest's downloads folder until the spice client disconnected, at + which point the vdagent would remove the unfinshed file. + + This CANCELLED status message was only being sent if the task was + canceled during the async file read operation. If you cancel a task, + it's quite likely that it will happen during other operations + (e.g. file_xfer_flush_async(), etc). In order to handle these scenarios + (and make sure that the file gets canceled properly), send the + FILE_XFER_STATUS message in spice_file_transfer_task_completed(). + +2016-04-07 Pavel Grunt + + Do not call spice_egl_cursor_set when egl is disabled + Fix memory leaks of cursor: + + 240 bytes in 1 blocks are possibly lost in loss record 10,786 of 12,521 + at 0x4C2FA60: calloc (vg_replace_malloc.c:711) + by 0x3700F861: ralloc_size (ralloc.c:113) + by 0x36FD2D68: UnknownInlinedFun (list.h:83) + by 0x36FD2D68: (anonymous namespace)::builtin_variable_generator::add_const(char const*, int) (builtin_variables.cpp:578) + by 0x36FD4775: generate_constants (builtin_variables.cpp:725) + by 0x36FD4775: _mesa_glsl_initialize_variables(exec_list*, _mesa_glsl_parse_state*) (builtin_variables.cpp:1303) + by 0x36E03D26: create_new_program (ff_fragment_shader.cpp:1225) + by 0x36E03D26: _mesa_get_fixed_func_fragment_program (ff_fragment_shader.cpp:1295) + by 0x36E9A577: update_program (state.c:157) + by 0x36E9A577: _mesa_update_state_locked (state.c:473) + by 0x36E9A6A0: _mesa_update_state (state.c:504) + by 0x36EB05E4: teximage (teximage.c:2947) + by 0x36EB211F: _mesa_TexImage2D (teximage.c:3009) + by 0x4E5024F: spice_egl_cursor_set (spice-widget-egl.c:497) + by 0x4E4BFD7: cursor_set (spice-widget.c:2346) + by 0x50D6245: g_cclosure_user_marshal_VOID__INT_INT_INT_INT_POINTER (spice-marshal.c:245) + + Use g_clear_pointer if possible + Acked-by: Eduardo Lima (Etrunko) + + Use g_clear_object if possible + Acked-by: Eduardo Lima (Etrunko) + + Use g_object_unref instead of gdk_cursor_unref + GdkCursor is GObject and gdk_cursor_unref has been deprecated since 3.0 + + Acked-by: Eduardo Lima (Etrunko) + + Use GMutex instead of GStaticMutex + Since GLib 2.32 GMutex can be statically allocated, so GStaticMutex has + been deprecated. + + Acked-by: Christophe Fergeau + + Use GDK_VERSION_MAX_ALLOWED + In order to avoid using a too new Gtk API. + + Taken from virt-viewer 4c4a43c61db60ac815c0bc66730fa0a9a1571103 + + Acked-by: Eduardo Lima (Etrunko) + + Use GLIB_VERSION_MAX_ALLOWED + In order to avoid using a too new GLib API. + + Taken from virt-viewer 96d120903f0b95d49642e58d4f796b4f62aa8b20 + + Acked-by: Eduardo Lima (Etrunko) + +2016-04-01 Pavel Grunt + + widget-egl: Define label only if can be used + The label can be used only with GDK_WINDOWING_WAYLAND + + Silence -Wunused-label + +2016-03-30 Pavel Grunt + + doc: Add description for spice_display_get_gl_scanout() + Acked-by: Christophe Fergeau + + doc: Ignore spicy-connect + Acked-by: Christophe Fergeau + + spice-file-transfer-task: Fix docstring + Acked-by: Christophe Fergeau + + doc: channel stability should be Stable + Acked-by: Christophe Fergeau + + doc: Remove private structs + Acked-by: Christophe Fergeau + + usb-device-manager: Fix docstring + Add description, "Since" and change the parameter name in the docstring + to match parameter name in the function definition. + + Acked-by: Christophe Fergeau + +2016-03-30 Christophe Fergeau + + build-sys: Update symbol files + The OSX-specific symbol files were not updated after the recent API + additions/removals, and some removed symbols were still listed in + map-file. + +2016-03-29 Victor Toso + + egl: fix leak when display is unrealize + eglTerminate should be called on unrealize. This not yet fix all the + leaks but reduces it significantly from 318kb to 74kb as definitely lost + and around 1mb to 8kb as indirectly lost. + + 4,096 bytes in 1 blocks are definitely lost in loss record + 9,762 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x35688320: can_write_oacontrol (intel_extensions.c:121) + by 0x35688320: intelInitExtensions (intel_extensions.c:279) + by 0x35651380: brwCreateContext (brw_context.c:875) + by 0x35602720: driCreateContextAttribs (dri_util.c:426) + by 0xF0C48B1: dri2_create_context (egl_dri2.c:1072) + by 0xF0BE727: eglCreateContext (eglapi.c:638) + by 0x5461D27: spice_egl_init (spice-widget-egl.c:256) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + by 0xB44C92E: g_signal_emit_valist (gsignal.c:3385) + by 0xB44CC51: g_signal_emit (gsignal.c:3441) + + 4,856 (32 direct, 4,824 indirect) bytes in 1 blocks are definitely lost + in loss record 9,779 of 9,882 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0xF0BEEF7: _eglCreateArray (eglarray.c:71) + by 0xF0BF420: _eglLinkConfig (eglconfig.c:90) + by 0xF0C4F8D: dri2_add_config (egl_dri2.c:307) + by 0xF0C66EE: dri2_x11_add_configs_for_visuals (platform_x11.c:766) + by 0xF0C80EC: dri2_initialize_x11_dri3 (platform_x11.c:1319) + by 0xF0C80EC: dri2_initialize_x11 (platform_x11.c:1464) + by 0xF0C18FE: _eglMatchAndInitialize (egldriver.c:261) + by 0xF0C19B8: _eglMatchDriver (egldriver.c:292) + by 0xF0BDD31: eglInitialize (eglapi.c:482) + by 0x5461A76: spice_egl_init (spice-widget-egl.c:226) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + + 5,921 (472 direct, 5,449 indirect) bytes in 1 blocks are definitely lost + in loss record 9,794 of 9,882 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0xF0C7E0E: dri2_initialize_x11_dri3 (platform_x11.c:1267) + by 0xF0C7E0E: dri2_initialize_x11 (platform_x11.c:1464) + by 0xF0C18FE: _eglMatchAndInitialize (egldriver.c:261) + by 0xF0C19B8: _eglMatchDriver (egldriver.c:292) + by 0xF0BDD31: eglInitialize (eglapi.c:482) + by 0x5461A76: spice_egl_init (spice-widget-egl.c:226) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + by 0xB44C92E: g_signal_emit_valist (gsignal.c:3385) + by 0xB44CC51: g_signal_emit (gsignal.c:3441) + by 0x5D2C9DB: gtk_widget_realize (gtkwidget.c:5454) + + 16,384 bytes in 4 blocks are definitely lost in loss record 9,854 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x3568AB30: intel_miptree_map_raw (intel_mipmap_tree.c:2149) + by 0x3568CEE6: intel_miptree_map_gtt (intel_mipmap_tree.c:2182) + by 0x3568CEE6: intel_miptree_map (intel_mipmap_tree.c:2774) + by 0x35692851: intel_map_texture_image (intel_tex.c:227) + by 0x35447C3B: store_texsubimage (texstore.c:1069) + by 0x35447E9F: _mesa_store_teximage (texstore.c:1125) + by 0x3543D9BA: _mesa_get_fallback_texture (texobj.c:1056) + by 0x35443E1E: UnknownInlinedFun (texstate.c:562) + by 0x35443E1E: update_program_texture_state (texstate.c:587) + by 0x35443E1E: UnknownInlinedFun (texstate.c:726) + by 0x35443E1E: _mesa_update_texture (texstate.c:757) + by 0x35420809: _mesa_update_state_locked (state.c:430) + by 0x35420ED0: _mesa_update_state (state.c:504) + by 0x3535BF87: _mesa_Clear (clear.c:172) + by 0x546214F: spice_egl_update_display (spice-widget-egl.c:514) + + 32,768 bytes in 1 blocks are definitely lost in loss record 9,864 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x35683E3C: intel_batchbuffer_reset (intel_batchbuffer.c:68) + by 0x35684052: brw_new_batch (intel_batchbuffer.c:164) + by 0x35684052: _intel_batchbuffer_flush.part.2 (intel_batchbuffer.c:397) + by 0x3568853B: can_write_oacontrol (intel_extensions.c:153) + by 0x3568853B: intelInitExtensions (intel_extensions.c:279) + by 0x35651380: brwCreateContext (brw_context.c:875) + by 0x35602720: driCreateContextAttribs (dri_util.c:426) + by 0xF0C48B1: dri2_create_context (egl_dri2.c:1072) + by 0xF0BE727: eglCreateContext (eglapi.c:638) + by 0x5461D27: spice_egl_init (spice-widget-egl.c:256) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + + 32,768 bytes in 1 blocks are definitely lost in loss record 9,865 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x35683E3C: intel_batchbuffer_reset (intel_batchbuffer.c:68) + by 0x35684052: brw_new_batch (intel_batchbuffer.c:164) + by 0x35684052: _intel_batchbuffer_flush.part.2 (intel_batchbuffer.c:397) + by 0x356887F3: can_do_pipelined_register_writes (intel_extensions.c:88) + by 0x356887F3: intelInitExtensions (intel_extensions.c:338) + by 0x35651380: brwCreateContext (brw_context.c:875) + by 0x35602720: driCreateContextAttribs (dri_util.c:426) + by 0xF0C48B1: dri2_create_context (egl_dri2.c:1072) + by 0xF0BE727: eglCreateContext (eglapi.c:638) + by 0x5461D27: spice_egl_init (spice-widget-egl.c:256) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + + 98,304 bytes in 3 blocks are definitely lost in loss record 9,872 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x35683E3C: intel_batchbuffer_reset (intel_batchbuffer.c:68) + by 0x35684052: brw_new_batch (intel_batchbuffer.c:164) + by 0x35684052: _intel_batchbuffer_flush.part.2 (intel_batchbuffer.c:397) + by 0x3564F834: intel_glFlush (brw_context.c:259) + by 0xF0C3DA0: dri2_make_current (egl_dri2.c:1189) + by 0xF0BAB1B: eglMakeCurrent (eglapi.c:703) + by 0x546274E: spice_widget_init_egl_win (spice-widget-egl.c:316) + by 0x546274E: spice_egl_realize_display (spice-widget-egl.c:333) + by 0x545B89F: drawing_area_realize (spice-widget.c:586) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + by 0xB44C92E: g_signal_emit_valist (gsignal.c:3385) + by 0xB44CC51: g_signal_emit (gsignal.c:3441) + + 131,072 bytes in 4 blocks are definitely lost in loss record 9,874 of 9,882 + at 0x35B19E40: drm_intel_gem_bo_map (intel_bufmgr_gem.c:1454) + by 0x35683E3C: intel_batchbuffer_reset (intel_batchbuffer.c:68) + by 0x356848E8: intel_batchbuffer_init (intel_batchbuffer.c:45) + by 0x35651337: brwCreateContext (brw_context.c:848) + by 0x35602720: driCreateContextAttribs (dri_util.c:426) + by 0xF0C48B1: dri2_create_context (egl_dri2.c:1072) + by 0xF0BE727: eglCreateContext (eglapi.c:638) + by 0x5461D27: spice_egl_init (spice-widget-egl.c:256) + by 0x545B885: drawing_area_realize (spice-widget.c:581) + by 0xB431784: g_closure_invoke (gclosure.c:804) + by 0xB443A40: signal_emit_unlocked_R (gsignal.c:3629) + by 0xB44C92E: g_signal_emit_valist (gsignal.c:3385) + + 1,080,655 (284 direct, 1,080,371 indirect) bytes in 1 blocks are + definitely lost in loss record 9,881 of 9,882 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0x355A2221: ralloc_size (ralloc.c:113) + by 0x355A227D: rzalloc_size (ralloc.c:134) + by 0x355A2BEE: ra_alloc_reg_set (register_allocate.c:196) + by 0x356D79AA: brw_alloc_reg_set(brw_compiler*, int) (brw_fs_reg_allocate.cpp:159) + by 0x356D817D: brw_fs_alloc_reg_sets (brw_fs_reg_allocate.cpp:305) + by 0x356FDACC: brw_compiler_create (brw_shader.cpp:84) + by 0x35691995: intelInitScreen2 (intel_screen.c:1495) + by 0x35602A5E: driCreateNewScreen2 (dri_util.c:144) + by 0xF0C547B: dri2_create_screen (egl_dri2.c:674) + by 0xF0C808F: dri2_initialize_x11_dri3 (platform_x11.c:1303) + by 0xF0C808F: dri2_initialize_x11 (platform_x11.c:1464) + by 0xF0C18FE: _eglMatchAndInitialize (egldriver.c:261) + + Acked-by: Marc-André Lureau + +2016-03-29 Pavel Grunt + + doc: Remove dropped functions + Dropped in 70a00b8fcc2ca85d3601f6ac4895f906f9032e77 + + Acked-by: Marc-André Lureau + + widget: Avoid combining ternary with another operators + Logical operators like "&&" has higher precedency than "?:". + Readiness of SpiceDisplay was wrongly determined due to missing + parentheses around the ternary operator. + + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=94738 + Acked-by: Victor Toso + +2016-03-29 Marc-André Lureau + + usb: fix build, missing ')' + +2016-03-24 Jonathon Jongsma + + usb device widget: don't try to disconnect on failed connect + When you try to redirect a usb device to the guest and it fails, we + uncheck the checkbox for this device. This causes the 'clicked' signal + to be emitted, which causes us to try to disconnect the device (which is + not currently connected, since the connect operation failed). + + When we try to disconnect an unconnected device, the device manager + leaks memory and gets left in an inconsistent state because we allocate + the task data, call _set_redirecting(self, TRUE) and then return early + with the following warning printed to the terminal: + + (lt-spicy:4638): GSpice-CRITICAL **: spice_usbredir_channel_disconnect_device_async: assertion 'channel != NULL' failed + + To avoid this, disable signal handlers for the checkbox 'clicked' + signal while we're changing the checkbox state in response to a + connection error. In addition, add an additional check to + spice_usb_device_manager_disconnect_device_async() to ensure that the + passed device is actually connected. + + SpiceUsbDeviceManager: propagate errors from sub-tasks + _connect_device_async_cb() just turned TRUE unconditionally even if the + sub-task had failed. Instead, introduce a + _spice_usb_device_manager_connect_device_finish() function which passes + up the result of the subtask. + +2016-03-24 Dmitry Fleytman + + UsbDeviceManager: Deprecate synchronous disconnection method + Asynchronous disconnection should be used instead. + + Acked-by: Jonathon Jongsma + +2016-03-24 Kirill Moizik + + UsbDeviceWidget: Use asynchronous disconnect API + Acked-by: Jonathon Jongsma + + UsbDeviceWidget: Consider asynchronous redirection flows + Gray out redirection controls while there are + asynchronous redirection flows in progress. + + Acked-by: Jonathon Jongsma + + UsbDeviceWidget: Show info bar during redirection flows + Acked-by: Jonathon Jongsma + + usbredir: Disconnect USB device asynchronously + Reviewed-by: Jonathon Jongsma + + UsbDeviceManager: Track device disconnection operations in progress + During device disconnection, unwanted hotplug events may happen. + We need to ignore those therefore we track disconnection operations + in progress. + + See also comment to commit + "Do not process USB hotplug events while redirection is in progress" + that introduces corresponding filtering out logic. + + Acked-by: Jonathon Jongsma + + UsbDeviceManager: Implement asynchronous disconnect device flow + This commit introduces functions for asynchronous disconnection flows. + Following commits will make use of those. + + Thread safety is ensured the same way it was done for connection + flow in previous commits. Disconnect logic is protected by the same + locks that protect connect/usbredir/channel management logic. + + UsbDeviceManager: Track device redirection operations in progress + During device connection, unwanted hotplug events may happen. + We need to ignore those therefore we track redirection operations + in progress. + + See also comment to commit + "Do not process USB hotplug events while redirection is in progress" + that introduces corresponding filtering out logic. + + usbredir: Spawn a different thread for device redirection flow + On Windows when using usbdk, opening and closing USB device handle, + i.e. calling libusb_open()/libusb_unref_device() can block for a few + seconds (3-5 second more specifically on patch author's HW). + + libusb_open() is called by spice_usbredir_channel_open_device(). + + libusb_unref_device() is called implicitly via + usbredirhost_set_device(..., NULL) from + spice_usbredir_channel_disconnect_device(). + + Both these calls happen on the main thread. If it blocks, + this causes the UI to freeze. + + This commit makes sure libusb_open() is called from a different + thread to avoid blocking the mainloop when usbdk is used. + + Following commits also move usbredirhost_set_device(..., NULL) call + to separate threads. + + Since this commit introduces additional execution contexts running in + parallel to the main thread there are thread safety concerns to be secured. + Mainly there are 3 types of objects accessed by newly introduced threads: + 1. libusb contexts + 2. usbredir context + 3. redirection channels + + Fortunately libusb accesses are either thread safe or already + performed by a separate thread and protected by locks as needed. + + As for channels and usbredir, in order to achieve thread safety + additional locks were introduced by previous patches + in preparation to adding asynchronous contexts: + + 1. Channel objects data accesses from different threads protected with a + new lock (device_connect_mutex); + 2. Handling usbredir messages protected by the same new lock in order to + ensure there are no messages processing flows in progress when device gets + connected or disconnected. + + usbredir: Protect data accessed by asynchronous redirection flows + This commit adds locking to ensure thread safety required + after start/stop redirection flows moved to separate threads. + This is done in preparation to following commits that + will introduce actual multithreaded access to corresponding + routines. + + Acked-by: Jonathon Jongsma + + GUdevClient: Do not process USB hotplug events while redirection is in progress + USB redirection flow on Windows includes a number of reset requests issued + to the port that hosts the device deing redirected. + + Each port reset emulates device removal and reinsertion and produces + corresponding hotplug events and a number of device list updates on + different levels of USB stack and USB redirection engine. + + As a result, queriyng USB device list performed by spice-gtk's hotplug + event handler may return inconsistent results if performed in parallel + to redirection flow. + + This patch suppresses handling of USB hotplug events during redirection + and injects a simulated hotplug event after redirection completion + in order to properly process real device list changes in case they + happened during the redirection flow. + + Acked-by: Jonathon Jongsma + + win-usb-dev: Track device redirection operations in progress + This commit introduces redirecting property of GUdevClient + + This property indicates when a redirection operation + is in progress on a device. It's set back to FALSE + once the device is fully redirected to the guest. + + Acked-by: Jonathon Jongsma + + usbredir: Introduce mutex for device (dis)connection + This commit introduces channel mutex to allow usage of + channel objects in mutithreaded environments. + + This mutex will be used by future commits to protect + thread unsafe usbredir functions and data structures. + + Acked-by: Jonathon Jongsma + +2016-03-24 Dmitry Fleytman + + win-usb-dev: Fix device (un)plug notification handler + This patch fixes device list change notification handing + logic for cases when more than one device being plugged + or unplugged simultaneously. + + The simplest way to reproduce the problematic scenario + is (un)plugging of a usb HUB with a few devices inserted. + + Acked-by: Jonathon Jongsma + + usb-dev-manager: Fix cbinfo leak in case of abnormal return + Acked-by: Jonathon Jongsma + + win-usbredir: Use UsbDk backend when available + Acked-by: Jonathon Jongsma + + win-usbredir: Do not use UsbClerk for non-WinUsb backends + Acked-by: Jonathon Jongsma + + win-usbredir: Move installer interaction logic to separate functions + This is a refactoring done in preparation for the next commits. + + Acked-by: Jonathon Jongsma + + usbdk: Load hide rules for auto-redirected devices + Hide rules order UsbDk to avoid showing specific USB + devices to Windows PnP manager. + + Spice-gtk loads hide rules for devices that should be + automatically redirected on connection to prevent Windows + from showing "New Hardware Found" wizard window for USB + devices that do not have driver on the local system. + + win-usbredir: Only match USB devices by VID:PID when WinUsb used + In other cases match devices by BUS:ADDR. + + This commit introduces use_usbclerk flag which is set TRUE + unconditionally for Windows builds for now. Next patches + will introduce UsbDk backend integrartion which will set + this flag in accordance to UsbDk presence on the system. + + Acked-by: Jonathon Jongsma + +2016-03-24 Christophe Fergeau + + Add SpiceUsbDeviceManager parameter to device comparison functions + This additional parameter is currently unused, but this is in + preparation for the next commits. + Acked-by: Jonathon Jongsma + +2016-03-24 Dmitry Fleytman + + win-usbredir: Introduce UsbDk wrapper + Introduce UsbDk API definitions and binding code. + + UsbDk API DLL is loaded dynamically and wrapped by + a thin glue code layer. This approach was chosen in + order to make spice-gtk functional without UsbDk + installed. + + Next patches will introduce dynamic backend selection + logic, i.e. spice-gtk will try to use UsbDk by + default and fallback to the old WinUsb/usbclerk + scheme in case UsbDk is not available. + + Acked-by: Jonathon Jongsma + +2016-03-24 Marc-André Lureau + + widget: modify update-area to not require primary surface + If egl display is enabled, use GL scanout geometry to check intersection + with the monitor area. This solves displaying GL display without + software canvas (currently d->area is empty and gl drawing fails) + + Acked-by: Pavel Grunt + + main: don't update display timer for unchanged config + With virgl, set_monitor_ready() may be called each time the scanout is + updated to set the monitor area. This will call + spice_main_update_display(), and keep the timer postponed even if the + monitor configuration didn't change. Treat unchanged configuration as a + no-op and keep configuration timer unchanged. This fixes monitor + autoconfig with virgl (when the display is regularly updated). + + It also solves/avoids problems with a guest running on wayland when the + "resize-guest" property is TRUE. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1266484 + + Acked-by: Jonathon Jongsma + + widget: update d->ready based on scanout image available + d->ready is updated based on monitor area & canvas. In case of GL + rendering, update it based on monitor area & scanout and add check + before drawing update. + + Acked-by: Pavel Grunt + + egl: check and update scanout after egl init + Once the egl/GL context are initialized, check if there is a scanout to + associate to display widget. This solves races when scanout update is + happening before the egl/GL context is ready. + + Acked-by: Pavel Grunt + + widget: make gl-scanout and update-monitor-area privately exported + The following changes will call these functions from spice-widget-egl.c + + Acked-by: Pavel Grunt + + display: return NULL in spice_display_get_gl_scanout() + If there is no valid scanout, return NULL. + + Acked-by: Pavel Grunt + + widget: enable egl before updating scanout + The GLArea is realized lazily, when it is made visible in + set_egl_enabled(). The egl context is initialized once the GLArea is + realized. Enable egl before updating the scanout. + + Acked-by: Pavel Grunt + + egl: check context is ready + Add a new GL status field to check if the GL context is ready. This + helps debugging races where GL is called before the context is ready. + + Acked-by: Pavel Grunt + + widget: remove superflous WIN32 check + The egl call is already inside a X11 conditional block. + + Acked-by: Pavel Grunt + +2016-03-24 Victor Toso + + channel-main: fix leak on volume-sync + 7 bytes in 1 blocks are definitely lost in loss record 128 of 10,009 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0xB6C3200: g_malloc0 (gmem.c:124) + by 0x740BD5F: audio_playback_volume_info_cb (channel-main.c:1216) + by 0xB11D488: g_task_return_now (gtask.c:1107) + by 0xB11DCBD: g_task_return (gtask.c:1165) + by 0x742D1F5: spice_pulse_complete_all_async_tasks (spice-pulse.c:1034) + by 0x8B6B57C: ext_stream_restore_read_cb (ext-stream-restore.c:141) + by 0x10BA63C0: run_action (pdispatch.c:284) + by 0x10BA6722: pa_pdispatch_run (pdispatch.c:337) + by 0x8B6520D: pstream_packet_callback (context.c:338) + by 0x10BA8D7E: do_read (pstream.c:879) + by 0x10BAB39A: do_pstream_read_write (pstream.c:189) + + 7 bytes in 1 blocks are definitely lost in loss record 129 of 10,009 + at 0x4C2A988: calloc (vg_replace_malloc.c:711) + by 0xB6C3200: g_malloc0 (gmem.c:124) + by 0x740BFBF: audio_record_volume_info_cb (channel-main.c:1273) + by 0xB11D488: g_task_return_now (gtask.c:1107) + by 0xB11DCBD: g_task_return (gtask.c:1165) + by 0x742D1F5: spice_pulse_complete_all_async_tasks (spice-pulse.c:1034) + by 0x8B6B57C: ext_stream_restore_read_cb (ext-stream-restore.c:141) + by 0x10BA63C0: run_action (pdispatch.c:284) + by 0x10BA6722: pa_pdispatch_run (pdispatch.c:337) + by 0x8B6520D: pstream_packet_callback (context.c:338) + by 0x10BA8D7E: do_read (pstream.c:879) + by 0x10BAB39A: do_pstream_read_write (pstream.c:189) + + Acked-by: Christophe Fergeau + +2016-03-23 Marc-André Lureau + + widget: use allocation instead of window size + Since spice-gtk 57df040cc, the SpiceDisplay no longer forces its own + window. Get allocation instead of window size. This fixes a "top + border" issue in spicy with gtk+ >= 3.19.8. + + Acked-by: Pavel Grunt + + widget: offset draw updates by widget allocation if necessary + According to gtk_widget_queue_draw_area() documentation: + + "The region here is specified in widget coordinates. Widget coordinates + are a bit odd; for historical reasons, they are defined as + widget->window coordinates for widgets that return TRUE for + gtk_widget_get_has_window(), and are relative to widget->allocation.x , + widget->allocation.y otherwise." + + Since spice-gtk 57df040cc, the SpiceDisplay no longer forces its own + window. During gtk+ 3.19.8, gtk stack also no longer use its own + window (commit 9d0e8401). In order to make drawing update resilient to + such changes, add a function applying offset if necessary. + + This solves drawing glitches and perceived slowness with spice-gtk git + and gtk+ >= 3.19.8. + + Acked-by: Pavel Grunt + +2016-03-23 Pavel Grunt + + spicy: Remove configure-event callback + It is a leftover - see "Remove GnomeRR code" + commit 30986505ba6041c293c38cb4b7f4b618a59f4716 + + Acked-by: Christophe Fergeau + Acked-by: Marc-André Lureau + +2016-03-23 Frediano Ziglio + + Avoid to access array with negative numbers + +2016-03-22 Fabiano Fidêncio + + vmcstream,gtask: Do idle ourself instead of leaving it to GTask's heuristic + Seems that GTask heuristic only makes sense in a non-coroutine case. + After opening a bug[0] on spice-gtk and a few discussions in the mailing + list, seems that is completely fine for coroutine code to deal with the + idle explicitly. + + Acked-by: Marc-André Lureau + + vmcstream,gtask: Fix crash when trying to use webdav + Don't try to get the cancellable from a task that is, for sure (ensured + by us), NULL. See the backtrace: + + #0 0x00007ffff29cf250 in g_task_get_cancellable () at /lib64/libgio-2.0.so.0 + #1 0x00007ffff78a9012 in spice_vmc_input_stream_read_all_async (stream=, buffer=0x7070f8, count=8, io_priority=, cancellable=0x7fffcc00a470, callback=0x7ffff788c190 , user_data=0x707b30) at vmcstream.c:187 + #2 0x00007ffff788c0ab in start_demux (self=0x707b30) at channel-webdav.c:498 + #3 0x00007ffff2700578 in g_closure_invoke () at /lib64/libgobject-2.0.so.0 + #4 0x00007ffff27135f0 in signal_emit_unlocked_R () at /lib64/libgobject-2.0.so.0 + #5 0x00007ffff271c43c in g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 + #6 0x00007ffff788acca in emit_main_context (opaque=0x7fffbfffe880) at gio-coroutine.c:200 + #7 0x00007ffff242bab3 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 + #8 0x00007ffff242be60 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0 + #9 0x00007ffff242c182 in g_main_loop_run () at /lib64/libglib-2.0.so.0 + #10 0x0000000000405df6 in main (argc=, argv=) at spicy.c:1897 + + It was pointed out during the review and, somehow, missed :-\ + + Acked-by: Victor Toso + +2016-03-22 Jeremy White + + Include gdk/gdkwayland.h anytime GDK_WINDOWING_WAYLAND is defined. + A specific GTK version check is not appropriate for this particular include. + This fixes compilation on Debian Jessie. + +2016-03-22 Pavel Grunt + + Remove extra checks before g_cancellable_disconnect() + If cancellable is NULL or handler_id is 0 the function does nothing. + Acked-by: Victor Toso + + usb-device-manager: Remove invalid return annotation + Acked-by: Victor Toso + +2016-03-22 snir sheriber + + usbredir_handle_msg: rename data to err_data + To better reflect what this variable is used for and change the declare + location such that it will be declared only if it should + Acked-by: Victor Toso + +2016-03-21 Fabiano Fidêncio + + mingw: Fix build failure due to epoxy/egl.h header + epoxy/egl.h header is not provided by mingw-epoxy package. + Let's avoid egl usage when building using mingw then. + + Acked-by: Marc-André Lureau + + channel-usbredir: Fix crash due to a Task returning earlier than expected + g_task_return_error() has been completing the task immediately, not + cleaning up/setting up the device state to STATE_DISCONNECTED. It's been + causing a double free when trying to redirect a device without having + the ACL permissions for doing it. See the backtrace: + + #0 0x00007ffff24dc07d in g_type_check_instance_is_fundamentally_a (type_instance=type_instance@entry=0x14779d0, fundamental_type=fundamental_type@entry=80) at gtype.c:4032 + #1 0x00007ffff24bc447 in g_object_unref (_object=0x14779d0) at gobject.c:3076 + #2 0x00007ffff7bafc2a in connect_cb (gobject=0x87d9a0 [SpiceUsbDeviceManager], res=0x96f830, user_data=0x143e0e0) + at usb-device-widget.c:485 + #3 0x00007ffff277f5a3 in g_task_return_now (task=0x96f830 [GTask]) at gtask.c:1106 + #4 0x00007ffff277fc4e in g_task_return (task=0x96f830 [GTask], type=) at gtask.c:1164 + #5 0x00007ffff786c277 in spice_usb_device_manager_channel_connect_cb (gobject=0x917940 [SpiceUsbredirChannel], channel_res=0x96f900, user_data=0x96f830) at usb-device-manager.c:1094 + #6 0x00007ffff277f5a3 in g_task_return_now (task=0x96f900 [GTask]) at gtask.c:1106 + #7 0x00007ffff277fc4e in g_task_return (task=0x96f900 [GTask], type=) at gtask.c:1164 + #8 0x00007ffff786699c in spice_usbredir_channel_open_acl_cb (gobject=0xa73b00 [SpiceUsbAclHelper], acl_res=0x96f9d0, user_data=0x917940) at channel-usbredir.c:300 + #9 0x00007ffff277f5a3 in g_task_return_now (task=0x96f9d0 [GTask]) at gtask.c:1106 + #10 0x00007ffff277fc4e in g_task_return (task=0x96f9d0 [GTask], type=) at gtask.c:1164 + #11 0x00007ffff27804d0 in g_task_return_new_error (task=0x96f9d0 [GTask], domain=, code=, format=) at gtask.c:1744 + #12 0x00007ffff786eade in cb_out_watch (channel=0x1488740, cond=G_IO_IN, user_data=0xa73b00) at usb-acl-helper.c:128 + #13 0x00007ffff21b8e3a in g_main_context_dispatch (context=0x647390) at gmain.c:3154 + #14 0x00007ffff21b8e3a in g_main_context_dispatch (context=context@entry=0x647390) at gmain.c:3769 + #15 0x00007ffff21b91d0 in g_main_context_iterate (context=0x647390, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3840 + #16 0x00007ffff21b94f2 in g_main_loop_run (loop=0x13d1ae0) at gmain.c:4034 + #17 0x00007ffff3ca5440 in gtk_dialog_run () at /lib64/libgtk-3.so.0 + #18 0x0000000000406a18 in menu_cb_select_usb_devices (action=0x9d62f0 [GtkAction], data=0x69aef0) at spicy.c:394 + #22 0x00007ffff24d28ff in (instance=, signal_id=, detail=) at gsignal.c:3439 + #19 0x00007ffff24b77a5 in g_closure_invoke (closure=0xa0d0c0, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7fffffffcf70, invocation_hint=invocation_hint@entry=0x7fffffffcef0) at gclosure.c:801 + #20 0x00007ffff24c9851 in signal_emit_unlocked_R (node=node@entry=0x63fc10, detail=detail@entry=0, instance=instance@entry=0x9d62f0, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffcf70) at gsignal.c:3627 + #21 0x00007ffff24d2530 in g_signal_emit_valist (instance=, signal_id=, detail=, var_args=var_args@entry=0x7fffffffd130) at gsignal.c:3383 + #23 0x00007ffff3bc23b0 in _gtk_action_emit_activate () at /lib64/libgtk-3.so.0 + #27 0x00007ffff24d28ff in (instance=, signal_id=, detail=) at gsignal.c:3439 + #24 0x00007ffff24b77a5 in g_closure_invoke (closure=closure@entry=0x6607d0, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7fffffffd3f0, invocation_hint=invocation_hint@entry=0x7fffffffd370) at gclosure.c:801 + #25 0x00007ffff24c938c in signal_emit_unlocked_R (node=node@entry=0x661050, detail=detail@entry=0, instance=instance@entry=0x9a8730, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffd3f0) at gsignal.c:3557 + #26 0x00007ffff24d2530 in g_signal_emit_valist (instance=, signal_id=, detail=, var_args=var_args@entry=0x7fffffffd5b0) at gsignal.c:3383 + #28 0x00007ffff3e7094e in gtk_widget_activate () at /lib64/libgtk-3.so.0 + #29 0x00007ffff3d4e4f6 in gtk_menu_shell_activate_item () at /lib64/libgtk-3.so.0 + #30 0x00007ffff3d4e824 in gtk_menu_shell_button_release () at /lib64/libgtk-3.so.0 + #31 0x00007ffff3d30fda in _gtk_marshal_BOOLEAN__BOXEDv () at /lib64/libgtk-3.so.0 + #32 0x00007ffff24b79d4 in _g_closure_invoke_va (closure=closure@entry=0x644d10, return_value=return_value@entry=0x7fffffffd900, instance=instance@entry=0x80faa0, args=args@entry=0x7fffffffd9d0, n_params=, param_types=0x644d40) at gclosure.c:864 + #33 0x00007ffff24d1dd3 in g_signal_emit_valist (instance=0x80faa0, signal_id=, detail=0, var_args=var_args@entry=0x7fffffffd9d0) at gsignal.c:3292 + #34 0x00007ffff24d28ff in g_signal_emit (instance=, signal_id=, detail=) at gsignal.c:3439 + #35 0x00007ffff3e6e4bc in gtk_widget_event_internal () at /lib64/libgtk-3.so.0 + #36 0x00007ffff3d2e34e in propagate_event () at /lib64/libgtk-3.so.0 + #37 0x00007ffff3d300fc in gtk_main_do_event () at /lib64/libgtk-3.so.0 + #38 0x00007ffff38a8e92 in gdk_event_source_dispatch () at /lib64/libgdk-3.so.0 + #39 0x00007ffff21b8e3a in g_main_context_dispatch (context=0x647390) at gmain.c:3154 + #40 0x00007ffff21b8e3a in g_main_context_dispatch (context=context@entry=0x647390) at gmain.c:3769 + #41 0x00007ffff21b91d0 in g_main_context_iterate (context=0x647390, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3840 + #42 0x00007ffff21b94f2 in g_main_loop_run (loop=0x6e2730) at gmain.c:4034 + #43 0x000000000040b2f9 in main (argc=1, argv=0x7fffffffde48) at spicy.c:1920 + + Acked-by: Pavel Grunt + +2016-03-18 Pavel Grunt + + Adjust to Gtk+ 3.10 + Dependency since f9a1aad85fcc76dd76c454b51fbce5e07c9b145f + + Remove unneeded GTK_CHECK_VERSION guards + + Acked-by: Victor Toso + + Adjust to GLib 2.36 + Dependency since 8693e7d3f7de1ff102082212fa6e35fb1a252ef7 + + Remove glib-compat files and most of GLIB_CHECK_VERSION guards + + Acked-by: Victor Toso + + Move strtok_r from glib-compat to spice-uri + It is not glib specific and it is only used in spice-uri + + Acked-by: Victor Toso + + spice-util: Fix alignment + Acked-by: Victor Toso + + usb-acl-helper: Remove extra check for NULL + g_cancellable_cancel() and g_clear_object() can handle it + + Acked-by: Victor Toso + +2016-03-17 Pavel Grunt + + spicy: s/Automagic/Automatic/ + Acked-by: Eduardo Lima (Etrunko) + + spice-display: Remove auto-clipboard notify + It was used to notify the (deprecated) auto-clipboard property of + the SpiceDisplay everytime the SpiceGtkSession emits its auto-clipboard + notify. + + The commit 70a00b8fcc2ca85d3601f6ac4895f906f9032e77 removed the property + from SpiceDisplay causing a runtime warning: + + GLib-GObject-WARNING **: g_object_notify: object class 'SpiceDisplay' has no property named 'auto-clipboard' + Acked-by: Eduardo Lima (Etrunko) + + display: Lower level of warning for empty monitor config + It is a valid case when a guest requests to turn off monitors, eg: + xrandr --output Virtual-0 --off + + Related: + https://bugzilla.redhat.com/show_bug.cgi?id=1061942 + + Acked-by: Frediano Ziglio + +2016-03-15 Marc-André Lureau + + build-sys: fix 'Only can be included directly' warning + Tests should be allowed to include directly private headers. Set + __SPICE_CLIENT_H_INSIDE__ where necessary or include spice-client.h + where possible. + + Acked-by: Fabiano Fidêncio + + Lower gtk+ requirement to 3.10 + Make GtkGlArea optional allows to lower gtk+ requirement to + 3.10 (required for GtkStack). However, gl display is unsupported on + wayland with gtk+ < 3.16. + + Acked-by: Fabiano Fidêncio + + build-sys: remove epoxy from pc requires + libepoxy doesn't need to figure in spice-gtk pkg-config requires, it's a + private dependency. + + Acked-by: Fabiano Fidêncio + +2016-03-14 Fabiano Fidêncio + + wocky-http-proxy: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + win-usb-driver-install: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + vmcstream: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + usb-device-manager: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + usb-acl-helper: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + spice-pulse: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + spice-gstaudio: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + spice-channel: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + smartcard-manager: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + channel-usbredir: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + channel-port: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + channel-main: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + + Acked-by: Jonathon Jongsma + + channel-base: Use GTask instead of GSimpleAsyncResult + Instead of using GSimpleAsyncResult, use the new GTask API, which is + much more straightforward. + For using the new GTask API, let's bump GIO (part of GLib) dependency + version to 2.36, which is safe based on major distro support: + - Debian Jessie: glib-2.42 + - RHEL-7.1: glib-2.40 + - SLES12: glib-2.38 + - Ubuntu LTS 14.04: glib-2.40 + + Acked-by: Jonathon Jongsma + +2016-03-14 Marc-André Lureau + + gtk: add GtkGLArea + GtkGLArea is the proper modern way to have opengl in an gtk+ + application. Unfortunately, it may use various backends and interfaces + to initialize it, but dmabuf image sharing requires egl atm. + + This patch keeps using our egl setup on X11, while it uses gtkglarea on + known gdk backend based on egl, such as the wayland one. This brings + wayland support for local gl to spice-gtk. + + Acked-by: Fabiano Fidêncio + + gtk: use GtkStack + Move the GtkDrawingArea in a GtkStack, so other widgets can be switched + to for the display: the next patch adds a GtkGLArea for an opengl + rendering. One can imagine other display widgets to show text etc.. + + Acked-by: Fabiano Fidêncio + + gtk: require gtk+ 3.16 + 3.16 is the minimal version for GtkGLArea widget, used in following + patches. + + Drop conditional epoxy support, as it is now required by gtk+. + + Acked-by: Fabiano Fidêncio + + gtk: drop deprecated stuff from spice-gtk + Breaking ABI is a good time to remove deprecated code. + + Acked-by: Fabiano Fidêncio + + Drop GTK+ 2.0 + Not so many systems require gtk+ 2.0 these days, let's move on. + + This drops the old python bindings (non-gir based), and the + unsteady/experimental gtk2-only XShm support. + + Acked-by: Fabiano Fidêncio + + gtk: make SpiceGrabSequence private + Do not leak internals of SpiceGrabSequence in public headers. This makes also + the class final, which let us extend more easily without fear of breaking ABI. + + Acked-by: Fabiano Fidêncio + + gtk: make SpiceUsbDeviceWidget private + Do not leak internals of SpiceUsbDeviceWidget in public headers. This makes also + the class final, which let us extend more easily without fear of breaking ABI. + + Acked-by: Fabiano Fidêncio + + gtk: make SpiceGtkSession private + Do not leak internals of SpiceGtkSession in our headers. This makes also + the class final, which let us extend more easily without fear of + breaking ABI. + + Acked-by: Fabiano Fidêncio + + gtk: make SpiceDisplay private + Do not leak internals of SpiceDisplay in our headers. This makes also + the class final, which let us extend more easily without fear of + breaking ABI. + + Acked-by: Fabiano Fidêncio + + build-sys: bump spice-gtk current version info + The following patches need to break the ABI (in particular the parent of the + SpiceDisplay widget). + + Acked-by: Fabiano Fidêncio + +2016-03-11 Marc-André Lureau + + build-sys: fix make check when polkit not available + acl-helper needs polkit (and unix atm) to build. + + doc: add a bunch of Since: 0.31 + + Prepare for v0.31 release + + logging: use more idiomatic spice-gtk logging + spice-gtk uses SPICE_DEBUG for debug lines (for now), and prefer direct + glib glog/g_warning. + + session: use debug message for optional key value + This fixes make check failing because of recent spice-common logging + switch to glib. + +2016-03-11 Jonathon Jongsma + + Update POTFILES.skip + spicy.desktop.in no longer exists. + + Add tests for usb-acl-helper + + usb-acl-helper: add env var for specifying acl helper binary + Setting SPICE_USB_ACL_BINARY allows us to execute a custom mock acl + helper binary for testing purposes. + + Rename spice_usb_acl_helper_open_acl() to _open_acl_async() + Follow established practice and make the function's behavior more + explicit. + + Remove spice_usb_acl_helper_close_acl() + This function is now only called after the open_acl() task completes, + and in that scenario it basically does the same thing that the + SpiceUsbAclHelper destructor does, so it's pointless. Remove it. + + usb-acl-helper: Avoid deadlock when cancelled + cancelled_cb() (which is triggered when the GCancellable's "cancelled" + signal is emitted) called spice_usb_acl_helper_close_acl(), which calls + spice_usb_acl_helper_cleanup(), which in turn calls + g_cancellable_disconnect(). Calling g_cancellable_disconnect() from + within a "cancelled" handler results in a dealock, as mentioned in the + documentation. Instead of closing the acl here, simply cancel the task + here. The cleanup() call will happen when the SpiceUsbAclHelper object + is destroyed. + + Introduce spice_usb_acl_helper_cancel() + This function explicitly cancels a open_acl() task. It is similar to + close_acl(), but its behavior is more explicit. This function is very + similar to the existing close_acl() function but it requires that the + task has not already been completed. Also, although it releases its + reference on priv->result to avoid circular references, it doesn't call + cleanup(), preferring instead to wait for the destructor to clean up. + This makes the close_acl() function essentially pointless and will be + removed in the following commit. + +2016-03-10 Marc-André Lureau + + Update spice-common submodule + Pick codegen build fix + +2016-02-23 Francois Gouget + + spice-gtk: Fix the signedness of a couple of mm-time traces + Acked-by: Marc-André Lureau + +2016-02-23 Ignacio Casal Quinteiro + + namedpipelistener: do not leak the error message + +2016-02-18 Christophe Fergeau + + Simplify spice_usb_device_manager_device_to_libdev() + The Windows-specific version duplicates some code from + spice_usb_device_equal_libdev(), this commit + switches to using that helper instead. + + Simplify spice_usb_device_equal_libdev() + The Windows-specific version duplicates some code from + spice_usb_device_manager_libdev_match(), this commit + switches to using that helper instead. + +2016-02-16 Marc-André Lureau + + gtk: add spice-widget GL scanout support + Hook to spice-glib events to show the GL scanout. + + The opengl context is created with egl, and is currently + x11-only (supporting wayland with bare-egl doesn't seem trivial). + + Using GtkGLArea is left for a future series, since SpiceDisplay widget + is a GtkDrawingArea and can't be replaced without breaking + ABI. Furthermore, GtkGLArea won't work on non-egl contexts, so this + approach is necessary on gtk+ < 3.16 or X11 (because gdk/x11 uses glx). + + Acked-by: Victor Toso + Acked-by: Pavel Grunt + +2016-02-13 Marc-André Lureau + + glib: add local GL scanout support + Add spice-glib support for gl scanout messages. + + A note about SpiceGlScanout: it is struct with scanout details, + registered as a boxed type, with associated gl-scanout property. That + way, it doesn't need a seperate signal for change notification and the + current scanout can be retrieve with gobject getter. Since boxed + property are always duplicated by g_object_get(), an additional + spice_display_get_gl_scanout() method returns the current scanout + without duplication (that's what spice-gtk display widget will use). + +2016-02-13 Marc-André Lureau + + build-sys: check for epoxy-egl support + The following code requires epoxy with egl support. Check for pkg-config + and egl headers. + + Add spice_channel_unix_read_fd() + Utility function used in the messages with socket ancillary fd. + +2016-02-13 Marc-André Lureau + + build-sys: bump to spice-protocol 0.12.11 + Needed for GL messages + +2016-02-12 Fabiano Fidêncio + + typo: s/GTask/GSimpleAsyncResult + Seems that I messed up with cd0c1008316e90bce925e1448ffcabb366e88f8f + while rebasing my GTask series on top of this patch, causing a build + breakage due to non-intentional insertion of a GTask replacing a + GSimpleAsyncResult. + + Acked-by: Pavel Grunt + + Use #ifdef {HAVE,USE}_FOO instead of #if {HAVE,USE}_FOO + While "#if USE_FOO" checks for the value of the variable USE_FOO, + "#ifdef" checks whether USE_FOO is defined or not. + + It means, if we had something like: #define USE_FOO 0, we would have: + #if USE_FOO + /* Any code in here would NOT be compiled */ + #endif + + #ifdef USE_FOO + /* Any code in here would be compiled */ + #endif + + No problem was faced on spice-gtk till now because either USE_FOO is not + defined or defined as 1, but let's try to have it standardized. + + Acked-by: Eduardo Lima (Etrunko) + +2016-02-03 Marc-André Lureau + + gtk: replace configure-event for size-allocate + For size-allocate, it's simpler to connect to the signal rather than + override the default signal handler since there is no automatic chaining + to parent handler otherwise. Doing this removes the need to have a + window. + + Acked-by: Victor Toso + +2016-01-22 Fabiano Fidêncio + + usb-device-{manager,widget}: Add counter of free channels + As the message showed when the last usbredir channel is taken can be a + bit confusing, let's add a counter of free channels to the widget's + label. + In order to add the counter, a new property for SpiceUsbDeviceManager + was introduced ("free-channels"). + + Related: rhbz#1298772 + + Remove GSLice usage + It's being slowly deprecated in glib + https://bugzilla.gnome.org/show_bug.cgi?id=754687 + +2016-01-19 Victor Toso + + gstaudio: set output parameter to NULL on error + This is not really triggered in the current code but this is usually + expected in case of errors; Also, the same function on record side + already does this. + + Acked-by: Jonathon Jongsma + +2016-01-14 Marc-André Lureau + + build-sys: silence vala deprecated function usage warnings + This silence usage of deprecated glib declarations from vala generated code. + + Acked-by: Fabiano Fidêncio + +2016-01-14 Marc-Andre Lureau + + Update spice-common + This is an update to fix build issues with spice-protocol.git. + generated_server_demarshallers.c: In function + ‘parse_msgc_display_gl_draw_done’: + generated_server_demarshallers.c:767:23: error: + ‘SpiceMsgcDisplayGlDrawDone’ undeclared (first use in this function) + mem_size = sizeof(SpiceMsgcDisplayGlDrawDone); + ... + + Also needed for upcoming gl-scanout messages. + + Acked-by: Frediano Ziglio + +2016-01-07 Victor Toso + + channel-main: remove unused header rect.h + It was included in be8ff99571478deb5c8d116134f65ed2b788dbd3 but with no + use. + + Acked-by: Marc-André Lureau + +2016-01-04 Marc-André Lureau + + build-sys: remove xrandr + Not needed anymore (probably since gnome-rr was removed in 30986505b) + +2015-12-21 snir sheriber + + Grab keyboard based on session focus. + When using multiple monitors moving mouse between monitors releases + keyboard grab. + + Reproduce bug + -Open multiple monitors remote-viewer session + -Click on one of the monitors to get focus & keyboard-grab + -Move mouse to another monitor and try keyboard command (do not click) + At this point all keyboard commands are being executed on the client + machine instead of the remote machine + + I added keyboard_has_focus and mouse_has_pointer variables at the + session and now these properties are being tested for the session + instead for the current widget (works also when using alt-tab). + + Resolves: rhbz#1275231 + + Acked-by: Pavel Grunt + +2015-12-21 Lukas Venhoda + + ppc: Fix spicy-screenshot colors on BE machines + Save screenshot in proper endianess + xRGB on LE machine and BGRx on BE machine + Acked-by: Pavel Grunt + + ppc: Fix colors on ppc when using GLZ + Fixes color order on PowerPC when using GLZ image compression. + Acked-by: Pavel Grunt + +2015-12-21 Fabiano Fidêncio + + ppc: Fix message endianess + + ppc: Fix header endianess + +2015-12-18 Pavel Grunt + + build-sys: Use sasl check from spice-common + Support only libsasl2 providing libsasl2.pc file + + Acked-by: Christophe Fergeau + +2015-12-10 Javier Celaya + + Call spice_marshaller_flush on message write + spice_marshaller_flush must be called before writing a message to + calculate pointer offsets. + + This is only an issue when ptr submarshallers are used, which currently + is only used by Tunnel::service_add. Since this is disabled by default, + this buug is not going to be hit by the current codebase. + +2015-12-09 Christophe Fergeau + + gst: Fix typo in preprocessor symbol + When the GStreamer backend is used, HAVE_GSTAUDIO is defined, not + HAVE_GST_AUDIO. + + smartcard: Fix compilation with older libcacard + e0c2182937 dropped some #include from channel-smartcard.c and spicy.c as + they were redundant with the headers already included from + spice-common/common/messages.h. While this is true for the newer + libcacard.h header, we need to include more headers to support older + libcacard, or compilation breaks. + +2015-12-09 Francois Gouget + + spice-gtk: Recover from GStreamer audio initialization errors + gst_init() will terminate the program in case of a failure so it's + better to use gst_init_check() so we can recover from errors. + +2015-12-08 Francois Gouget + + build-sys: Warn about missing GStreamer 1.0 audio runtime elements + Their absence should not be reported as an error since they are not + needed for the build, but the developer will need them to test the code + so it's appropriate to warn him. + +2015-12-08 Christophe Fergeau + + build-sys: Check for GStreamer 1.0 audio with SPICE_CHECK_GSTREAMER() + +2015-12-08 Francois Gouget + + build-sys: Allow simultaneous support for Pulse and GStreamer audio + Rather than GStreamer/PulseAudio backend being mutually exclusive at + compile-time, this commit allows to enable both at the same time. + PulseAudio will then be favoured, with a fallback to GStreamer if it's + not available. + Note that --with-audio is kept for backward compatibility. + +2015-12-08 Marc-André Lureau + + Use libcacard.h if possible + Drop unneeded includes (that are already undirectly included). + + Remove unmaintained spicy.nsis + Remove gtkrc too, and cleanup EXTRA_DIST ($(desktop_in_files) is unused) + + Update spice-common + For new libcacard.h usage + + Fix use after free of uri + "path" points to "uri" memory, move free(uri) later. + + Found thanks to valgrind :) + +2015-11-25 Christophe Fergeau + + Update spice-common submodule + The next commit is going to use SPICE_WARNING which was added recently + to spice-common + + This submodule update changes: + + Christophe Fergeau (5): + build-sys: Add gio-2.0 to SPICE_CHECK_GLIB2 + build-sys: Fix error in SPICE_CHECK_LZ4 description + build-sys: Set automake conditional in SPICE_CHECK_SMARTCARD + build-sys: Rename SUPPORT_GL to HAVE_GL + build-sys: Add missing # to comment + + Francois Gouget (3): + build-sys: Add the SPICE_WARNING() and SPICE_PRINT_MESSAGES m4 macros + build-sys: Add SPICE_CHECK_GSTREAMER() + build-sys: Add SPICE_CHECK_GSTREAMER_ELEMENTS() + + Lukas Venhoda (4): + ssl-verify: Only check addr length when using IP addr + m4: Require glib version >= 2.22 + ssl-verify: Changed IPv4 hostname to IPv6 + canvas_base: Remove redundant switch case block + +2015-11-25 Francois Gouget + + build-sys: Use SPICE_WARNING() to issue the DBus warning + +2015-11-24 Francois Gouget + + build-sys: Prefix the configure audio GStreamer variables with GSTAUDIO_ + This lets us avoid naming conflicts when using GStreamer for other + purposes. + + Acked-by: Victor Toso + +2015-11-19 Jay.han + + file transfer: send cancel message when user cancels a transfer + When a user cancel's a file transfer, we should send a STATUS_CANCELED + message rather than an STATUS_ERROR message. The latter triggers a bug + in the vdagent where the file remains opened by the vdagent in the guest + and cannot be removed. + +2015-11-19 Marek Kasik + + Be more specific in the case of authentication error + This patch adds SPICE_CLIENT_ERROR_AUTH_NEEDS_USERNAME error + for the case when authentication fails because of missing username. + This can happen when GSSAPI method is used. + + https://bugs.freedesktop.org/show_bug.cgi?id=92994 + +2015-11-18 Pavel Grunt + + spicy: Add support for changing compression + + channel-display: Add spice_display_change_preferred_compression + +2015-11-11 Pavel Grunt + + Do not export symbol of non-existent function + +2015-11-10 Jonathon Jongsma + + file xfer: Fix segfault when rebooting + Recent changes to file transfer introduced a regression where the client + would crash when rebooting a guest after performing a file transfer. + This was caused because the SpiceFileTransferTask is freed when it is + completed, but is not removed from the MainChannel's hash table. When we + reboot the guest and lose our vdagent connection, we iterate through the + list of tasks in the hash table and complete them. But since we did not + remove the already-completed tasks from this hash table, this hash table + contains already-freed memory. + + To fix the issue, take an extra ref for the async operations (so that + completing the task won't free an object that is stored in the hash table). In + addition, connect to the task's "finished" signal and remove it from the hash + table when it becomes finished. + + Bug reported via email by Jay.han . Valgrind report + below: + + ==6926== Invalid read of size 8 + ==6926== at 0x508177B: spice_file_transfer_task_completed (channel-main.c:2941) + ==6926== by 0x50846DC: set_agent_connected (channel-main.c:462) + ==6926== by 0x5073A43: spice_channel_recv_msg (spice-channel.c:1892) + ==6926== by 0x5073BE3: spice_channel_iterate_read (spice-channel.c:2132) + ==6926== by 0x5075D25: spice_channel_coroutine (spice-channel.c:2170) + ==6926== by 0x50A6EFE: coroutine_trampoline (coroutine_ucontext.c:63) + ==6926== by 0x50A6CC8: continuation_trampoline (continuation.c:55) + ==6926== by 0x65C2B5F: ??? (in /lib/x86_64-linux-gnu/libc-2.19.so) + ==6926== by 0x151331C7: ??? + ==6926== Address 0x29971fd8 is 168 bytes inside a block of size 184 free'd + ==6926== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) + ==6926== by 0x5E33142: g_type_free_instance (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4000.0) + ==6926== by 0x50815DA: file_xfer_close_cb (channel-main.c:1826) + ==6926== by 0x5AEBD5C: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.4000.0) + ==6926== by 0x5B0F41A: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.4000.0) + ==6926== by 0x5B0F438: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.4000.0) + ==6926== by 0x609BCE4: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4000.0) + ==6926== by 0x609C047: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4000.0) + ==6926== by 0x609C309: g_main_loop_run (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4000.0) + ==6926== by 0x4058AB: main (spicy.c:1858) + +2015-11-10 Francois Gouget + + build-sys: Remove some dead configure.ac DBus code + Acked-by: Christophe Fergeau + +2015-11-04 Francois Gouget + + spice-gtk: Fix error handling in stream_get_current_frame() + *data must always be set to NULL on error. + +2015-10-30 Victor Toso + + channel-usbredir: drop isoc packets on low bandwidth + When channel wants to send much more data then the wire can handle, the + queue grows fast. This patch does not limit the queue growth but + introduces an internal API to check if queue size is too big. + + This internal API is used in usbredir_buffered_output_size_callback + which is called before any isoc pacaket is queued in usbredir. The + usbredir implements the logic to: + - only drop isoc packets + - while dropping packtes does still give us video frames from and above + 10fps streams + + An easy way to test locally is sharing and webcam and with tc: + tc qdisc add dev lo root netem delay 100ms + tc qdisc change dev lo root netem delay 1000ms + tc qdisc del dev lo root netem + + Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1264156 + +2015-10-23 Christophe Fergeau + + build-sys: Remove unused conditional + + Adjust to spice-common spice-deps.m4 changes + This commit updates spice-common to latest git master. + Since the argument to the SPICE_CHECK_xxx macros is now unused, it's + cleaner to remove it. + + Christophe Fergeau (3): + Add marshaller test case + build-sys: Use ${PKG_CONFIG} rather than pkg-config + build-sys: Rework SPICE_CHECK_* m4 macros + + Frediano Ziglio (1): + common: Fix typo in comment + + Javier Celaya (1): + Fix linearization of several marshallers with one item + +2015-10-22 Jonathon Jongsma + + Remove noisy debug statement + This isn't terribly useful for general debugging and makes the log + pretty noisy when transferring large files. + + Don't print error message on successful file transfer + In certain circumstances we were printing an error message even though + the file transfer had completed successfully. It didn't cause any + problems, but it pointed out an issue in the handling of outgoing agent + messages. + + The described behavior was generally only encountered when there were multiple + files being transferred at once, and most often when one or two files were + significantly smaller than another file being transferred. For example, two + 20kB files and another 3MB file. The failure mechanism is basically as follows: + + For each file transfer, we read a chunk for the file and then we queue a series + of messages to the guest and wait for them to be flushed before continuing to + read a new chunk of the file. (Since the maximum agent message size is 2kB, each + 64kB chunk of file being read can generate up to 32 messages at a time). The + file transfer task remains in "pending" state until the flush operation is + complete. Since all agent messages go into a single channel-wide queue, waiting + for the messages to be flushed meant waiting for *all* outgoing messages to be + flushed, including those that were queued after we called flush_async(). + + Since agent messages can only be sent if the client has enough agent tokens, it + can take a little while for all queued messages to be sent. This means that + even if a file transfer task has sent out all of its data to the guest, it can + be kept in "pending" state for some time if other file transfer tasks or other + agent messages are added to the queue. In this situation, The guest might + notice that it has received all of the data for a file transfer task and send a + XFER_STATUS_SUCCESS message while we're still in "pending" state. + + This patch changes to code so that flush_async() only waits for the + currently-queued messages to be sent. This means that it is not affected by any + new messages that get added to the outgoing queue after we've called + flush_async(). This means that the task will exit "pending" state immediately + after sending out our last data packet. + + Fixes: rhbz#1265562 + + MainChannel: move task free from finalize to dispose + In order to avoid reference cycles, you're supposed to release + references in dispose, especially to those objects that can hold + references to yourself. This probably wasn't causing any leaks, since + the file transfer tasks generally are not alive when the main channel is + destroyed, but it's more proper. + +2015-10-16 Jonathon Jongsma + + FileTransferTask: ensure we emit 'finished' signal + In the case where a file cannot be opened for reading, we were not + emitting a 'finished' signal to communicate the error to the client. + + I was intending to further fix this issue by 'rejecting' the drop (in + SpiceDisplay) when the URI list contains invalid files (e.g. + directories). This would prevent a 'new-file-transfer' signal from even + being emitted for these invalid files. But this turns out to be not very + useful since there's no real feedback given to the user to indicate why + the drop failed. So it's probably better for client applications to get + the 'new-file-transfer' and 'finished' signals so that they can present + the error to the user to explain why the attempted transfer did not + work. + +2015-10-14 Christophe Fergeau + + Free display_cache in cache_unref + Otherwise it will be leaked. There is no cache_ref function, or helper + increasing a refcount/taking a reference so cache_unref really is a + cache_free method. + + This fixes: + + ==27687== 64 bytes in 4 blocks are definitely lost in loss record 250 of 435 + ==27687== at 0x4C28C50: malloc (vg_replace_malloc.c:299) + ==27687== by 0xA6AF058: g_malloc (gmem.c:94) + ==27687== by 0xA6C5982: g_slice_alloc (gslice.c:1007) + ==27687== by 0x40F112: cache_new (spice-channel-cache.h:54) + ==27687== by 0x40F112: cache_image_new (spice-channel-cache.h:64) + ==27687== by 0x40F112: spice_session_init (spice-session.c:294) + ==27687== by 0xA239B4A: g_type_create_instance (gtype.c:1870) + ==27687== by 0xA21C31A: g_object_new_internal (gobject.c:1779) + ==27687== by 0xA21DB10: g_object_newv (gobject.c:1926) + ==27687== by 0xA21E3FB: g_object_new (gobject.c:1619) + ==27687== by 0x40FF4D: spice_session_new (spice-session.c:1479) + ==27687== by 0x40E678: test_session_uri (session.c:35) + ==27687== by 0xA6CE47A: test_case_run (gtestutils.c:2158) + ==27687== by 0xA6CE47A: g_test_run_suite_internal (gtestutils.c:2241) + ==27687== by 0xA6CE642: g_test_run_suite_internal (gtestutils.c:2253) + + Rename display_cache::cache_unref to cache_free + display_cache is no longer refcounted since commit c9d4773, but this is + not an issue as even before, the fact that it was refcounted was not + used as there was no corresponding cache_ref() call (and + g_hash_table_ref() was not called directly either). + As the next commit will free memory from cache_unref() rather than just + releasing a reference, it's better to make it obvious that this method + is a _free() method rather than an _unref() one. + +2015-10-09 Jonathon Jongsma + + New file transfer API + There were several shortcomings to the existing file transfer API, + particularly in terms of monitoring ongoing file transfers. The major + issue is that spice_main_file_copy_async() allows you to pass an array + of files, but the progress callback does not provide a way to + identify which file the callback is associated with. This makes it + nearly impossible for an application to monitor file transfers. + + In addition, the SpiceDisplay widget automatically handles drag-and-drop + actions on the widget, and initiates file transfers without allowing the + application to specify a progress callback. So there's no way for an app + to monitor file transfers that are initiated via drag and drop. + + http://lists.freedesktop.org/archives/spice-devel/2015-September/021931.html + has a more detailed explanation of the issues. + + This change doesn't break the existing API, but adds some new API that + will allow an application to monitor file transfer progress, even for + transfers that are initiated within spice-gtk itself. + + - A new public SpiceFileTransferTask object is added. + - The SpiceMainChannel object gains a "new-file-transfer" signal that is + emitted whenever a new file transfer is initiated. The + SpiceFileTransferTask object is passed to the signal handler. + - The application can retain this object and monitor its 'progress' + property to be notified when the progress of the file transfer + changes. The SpiceFileTransferTask::finished signal indicates when the + given file transfer has completed. The application can also cancel the + file transfer by calling the _cancel() method. + + The 'spicy' test application has been updated to use this new API and + display a simple dialog showing the progress of individual files. + + Fix progress monitoring in spice_main_file_copy_async + spice_main_file_copy_async() allows you to pass a NULL-terminated array + of files to transfer to the guest. It also allows you to pass a + progress_callback function to monitor the progress of the transfer, but + this progress callback is called separately for each file that is + transferred, and there are no parameters that allow the caller to + determine which file a given callback corresponds to. This makes it very + difficult to monitor the progress. + + To make this more usable, I've changed it so that the progress callback + doesn't simply report the number of bytes read and total size of the + current file. Instead, we add up the status of all current transfers and + report that value to the callback. + + Don't wrap included headers in G_BEGIN|END_DECLS + Only the local declarations should be declared extern "C", otherwise it + can result in unexpected errors such as this (encountered while re-ordering + some include statements for a different patch): + + CC channel-inputs.lo + In file included from /usr/include/glib-2.0/glib/gmacros.h:38:0, + from /usr/lib64/glib-2.0/include/glibconfig.h:9, + from /usr/include/glib-2.0/glib/gtypes.h:32, + from /usr/include/glib-2.0/glib/galloca.h:32, + from /usr/include/glib-2.0/glib.h:30, + from /usr/include/glib-2.0/gobject/gbinding.h:28, + from /usr/include/glib-2.0/glib-object.h:23, + from /usr/include/glib-2.0/gio/gioenums.h:28, + from /usr/include/glib-2.0/gio/giotypes.h:28, + from /usr/include/glib-2.0/gio/gio.h:26, + from ../../src/spice-channel.h:27, + from ../../src/channel-inputs.h:25, + from ../../src/channel-inputs.c:20: + /usr/lib/gcc/x86_64-redhat-linux/4.9.2/include/stddef.h:147:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'typedef' + typedef __PTRDIFF_TYPE__ ptrdiff_t; + ^ + + Gtk applications should only include spice-client-gtk.h + This header is the single include needed for all gtk-related + functionality, similar to spice-client.h. Generate a compiler warning if + a different header is included. + + Glib applications should only include spice-client.h + Generate a compiler warning if an application attempts to include a + different header. + +2015-09-28 Jonathon Jongsma + + Fix documentation for spice_main_file_copy_async() + 'sources' should be a NULL-terminated array, but the parameter + documentation treats it as if it is a single file object. + +2015-09-25 Jonathon Jongsma + + Update NEWS for 0.30 release + + Move glib-compat.c to POTFILES.skip + Since these messages are only used for terminal debug output, let's not + waste time translating them. + +2015-09-25 Pavel Grunt + + docs: Fix typos + + docs: Add missing symbol description strings + + docs: Description should be above 'Return' + + docs: Add missing parameter/field descriptions + + docs: Move SPICE_TYPE_USB_DEVICE to standard subsection + + docs: Add Version Information section + + docs: Update for missing symbols + + channel-main: Rename parameter to match docs + + channel-record: Use correct nick name for property + +2015-09-23 Jonathon Jongsma + + Add glib-compat.c to POTFILES.in + Some translatable strings were added in commit 8c37a340. + +2015-09-18 sstuts + + Add "monitors config position" capability. + This will allow Windows guests to determine if the client supports a + monitors_config message from a multi-monitor guest that is not + multi-headed, i.e., that has one monitor per driver. + + It keeps commit:8b0cd321d5a4d08ccba5845c5f2206e6f8032c1d + from breaking if an updated win-qxl driver is paired with an older client. + + This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1248189 + --- + Changed from v1: Removed a local commit that preceded this one. + --- + Changed from v2: Changed name to "monitors config position" + --- + +2015-09-15 Christophe Fergeau + + build-sys: Fix spice-protocol requirements in .pc file + Commit d0ae58a8 added spice-protocol >= 0.12.10 to the Requires.private + field in spice-client-glib.pc. However it's already present in the + Requires field without a version check. Once spice-gtk is built and + installed, building a program against spice-gtk needs spice-protocol, + but no specific version of it, so we can drop the duplicate + Requires.private requirement, and keep the unversioned one in Requires. + +2015-09-10 Jonathon Jongsma + + Don't send monitors config when Display widget is created + When a display channel is associated with a particular SpiceDisplay + widget, it previously set the display to 'enabled' unconditionally. + There is a couple of problems with this behavior. + + First, simply because a display widget has an associated display + channel, it doesn't necessarily mean that the display is enabled. On + linux guests, for instance, a display channel can have up to 4 displays + for one channel, and perhaps only one of them is enabled. So, we + shouldn't set the display to 'enabled' until we actually receive a + monitors configuration message indicating that this display is enabled. + + The second problem is that this was triggering the client to send down a + new monitors-config message to the server. This message is completely + unnecessary since it is triggered by a message from the server. We + should only be sending down new monitor configurations in response to + changes from the client, not from the server. + + Add spice_main_update_display_enabled() + This is a new function that allows the caller to decide whether to send + the new status down to the server or not (analogous to the difference + between spice_main_set_display() vs spice_man_update_display()). + + This new function is needed to reduce unnecessary MonitorsConfig + messages from being sent to the server. Because spice-gtk does not + maintain any display state internally, it depends on the application to + maintain that state. Some state changes come from the server itself + (e.g. the guest has changed resolution due to some activity within the + guest), and some come from the application (e.g. the user has resized + the window of the client). Changes that come from server updates do not + need to be sent back down to the server, whereas those that originate + from the application *do* need to be sent to the server. + +2015-09-09 Pavel Grunt + + file-xfer: Simplify time handling + Use g_get_monotonic_time() instead of g_date_time_new_now_local(). + g_get_monotonic_time doesn't suffer discontinuities and it is sufficient + for our purposes. There is no need for the complexity of GDateTime. + +2015-09-08 Victor Toso + + audio: Do not volume-sync without audio + In case audio backend is not initialized correctly or there isn't audio + in the VM, we should not try to volume-sync. + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1257210 + +2015-08-25 Pavel Grunt + + file-xfer: Add debug messages about a file transfer progress + During the file transfer debug messages about the progress are printed + every 20 seconds for each of the file transfer tasks. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1140512 + + Acked-by: Frediano Ziglio + + glib-compat: Add g_format_size + g_format_size_for_display is deprecated since glib 2.30. See glib commit + afd1e3697065c1bd23fe9a1cacf43d8744d0bc9b + + g_format_size will be used in the following commit + + Acked-by: Frediano Ziglio + +2015-08-21 Marc-André Lureau + + session: update spice_session_connect() doc + Update the documentation about the return value, and how to watch for + connection success. + + Releated to: + https://bugzilla.redhat.com/show_bug.cgi?id=1253848 + +2015-08-14 Christophe Fergeau + + Adjust to new SpiceImageCompress name + This has been renamed to SpiceImageCompression in order to avoid clashes + with older spice-server in the SPICE_IMAGE_COMPRESS_ namespace. This + commit is a straight rename of SpiceImageCompress to + SpiceImageCompression and SPICE_IMAGE_COMPRESS_ to + SPICE_IMAGE_COMPRESSION_ + + build-sys: Remove spice-protocol submodule + It's seeing regular releases and is API stable, so we don't need to + bundle it with spice-gtk + +2015-08-05 Christophe Fergeau + + usbredir: Add a few debug logs + Currently, spice-gtk debugging logs contain no traces of the + values of the auto-redir/redir-on-connect filter, and it does not tell + you about the vid/pid of the devices being connected/redirected. + This commit adds the appropriate SPICE_DEBUG/CHANNEL_DEBUG calls so that + this data is logged. + + channel: Don't warn when no CA is set + Since v0.22~19 "Use system-wide trust certificate store", when neither + SpiceSession::ca-file nor SpiceSession::ca are set, the system-wide + CA store will be used to validate the SPICE certificates. + However, there is still a g_warn_if_fail() checking that either ca or + ca-file are set, which causes a runtime warning when trying to use the + system-wide store. This commit removes it. + +2015-08-03 Pavel Grunt + + Notify about existence of monitor for all display channels + Windows guest can have disabled display on the display chanel #0, in + that case it will not be listed in virt-viewer's "View->Displays" menu + + Resolves: + https://bugs.freedesktop.org/show_bug.cgi?id=91489 + +2015-07-28 Sandy Stutsman + + Handle single headed monitors that have a non-zero x, y config + Each monitor on a Windows guest is represented as a separate, single-headed + device with its own framebuffer. When there are multiple monitors, all + monitors but one will have a non-zero xy config position. But even in + these cases the whole area (frame-buffer) of each monitor should be + updated. + + Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1202419 + +2015-07-28 Jeremy White + + Add the gtk libraries to the gtk-scandoc link line. + This prevents a compile error on Debian Jessie, when building from git. + + This is fairly subtle, and Debian specific. It only happens when you use + autoreconf to generate a new libtool script. Debian patches that script + to require an explicit setting to link with all dependent libraries. + + It should be harmless on other distros, and it does save us Debian guys some + hassle. + +2015-07-13 Pavel Grunt + + Use g_return_val_if_fail instead of wrong g_return_if_fail + The commit 4b5e6ec2114e1250c81027ebeac9cfe8d059153f introduced a function + returning gboolean, g_return_val_if_fail() should be used instead of + g_return_if_fail(). + + Send monitor config if at least one monitor has dimensions + If a client (virt-manager, spicy) is not setting display dimensions + and the "resize-guest" property is disabled, spice-gtk sends a wrong + monitor config message where all the monitors have width = heigh = 0 + when the agent connects. This message can confuse the guest, in that + case the guest will change the resolution of its monitor. + + Regression since 28312b8d1e287a320851e8828825f2ca138d8b0b + + Resolves: + https://bugzilla.redhat.com/show_bug.cgi?id=1240721 + +2015-07-10 Sandy Stutsman + + This adds reference counting to cached images. + Windows guests with multi-monitors will often send down the same image + via different channels. If these instances are not counted, one channel + can delete an image before all the rest of the channels are finished with + it. In this case, the client will hang. + + This can happen, for instance, when the Windows guest is updating the + monitor's wallpaper. There is a driver instance for each monitor, so each + one is sending down its own copy of the same image with the same id. As + one channel may be busier than another, the order that the client executes + commands may not be the same order as the server issued them. Here's what + can happen: + + On the server side: + Monitor 1 sends image A + Monitor 1 sends multiple rendering commands for image A + Monitor 1 removes image A + Monitor 2 sends image A + Monitor 2 sends rendering commands for image A + On the client side: + Monitor 1 adds image A to the cache + Monitor 1 starts rendering with image A + Monitor 2 adds image A to the cache - has same id, so image is replaced + Monitor 1 removes image A - image A is completely removed from cache + Monitor 2 render command hangs waiting for image A + + Addresses bug: https://bugzilla.redhat.com/show_bug.cgi?id=1194354 + +2015-07-06 Christophe Fergeau + + Update spice-protocol + This will fix EL6 builds. + + Christophe Fergeau (1): + m4: Add compat AS_VAR_APPEND for older autoconf + + Lukas Venhoda (3): + ppc: Fix quic decode endianess + ppc: Fix lz magic endianess + ppc: Fix quic magic endianess + +2015-06-30 Jonathon Jongsma + + Make monitors config debug output more clear + Indicate whether the monitors config debug output is from sending or + receiving new monitors configuration. You can tell this by looking at + which channel is involved (main vs display), but making it more explicit + is helpful for glancing through logs. + +2015-06-29 Javier Celaya + + Display: Send a preferred compression message on init. + If the user prefers a specific compression algorithm, report it when + setting up the display channel. + + Add a preferred-compression program option + + Spice-session: Add preferred-compression property. + Also, depend on the spice-common commit that introduces the + SpiceImageCompress enum. + +2015-06-26 Christophe Fergeau + + build-sys: Fix build with automake < 1.13 + AC_CONFIG_MACRO_DIRS is not available with older automake versions, + which causes autogen.sh failures on RHEL6. m4_include() can be used + instead. + +2015-06-25 Pavel Grunt + + Send monitor config if guest supports sparse monitors + It is ok to send monitor configuration even for displays which are not + disabled or enabled. Because the guest having support for the sparse + monitor configuration (VD_AGENT_CAP_SPARSE_MONITORS_CONFIG) will not + resize the monitor which is disabled / undefined. + + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=90914 + + channel-main: Use enum to describe display state + +2015-06-22 Christophe Fergeau + + build-sys: Use SPICE_CHECK_LZ4 + spice-common now has an m4 macro adding a --enable-lz4 option and + doing the needed checks, so we can use it in configure.ac rather than + duplicating it here. + + build-sys: Use SPICE_CHECK_SMARTCARD + spice-common has an m4 macro adding a --enable-smartcard option and + doing the needed checks, so we can use it in configure.ac rather than + duplicating it here. + +2015-06-19 Christophe Fergeau + + spicy-*: Remove translation support + These are only meant to be test tools so they don't need to be + translated. + +2015-06-18 Lukas Venhoda + + spicy: Enable recent chooser on windows + Recent chooser is working correctly in windows. + + spicy: Replace duplicated code with a for loop + Changed piece of code working with fixed size array into a for loop. + + spicy: Host and port (or tls) are now required + Connect button is now non-sensitive when host and port (or tls) entry is empty. + Pressing enter will now also NOT connect, when the entries are empty. + + spicy: Fixed reselecting in recent chooser + Selecting an entry in the recent connections list, and then modifying + the host/port/TLS port, and double-clicking on that same entry in the + list would cause spicy to connect to the edited address rather than + the one which was picked in the recent chooser. + + After this commit, the selection will be cleared from the recent + chooser, and double-clicking on an entry after editing it will always + trigger a 'selection-changed' signal, which will properly set the + address to connect to. + + spicy: Changed the dialog into a window + Changed connect dialog from GtkDialog to GtkWindow. + + Added the necessary signals and buttons, to keep then + behaviour of a dialog (ESC to close, ENTER to submit). + + spicy_connect_dialog now returns TRUE and FALSE instead of 0 and -1. + + spicy: Move connect dialog to its own file + Connect dialog from spicy is now in its own file. + + Renamed connect_dialog to spicy_connect_dialog. + + Added new file for translation. + +2015-06-18 Victor Toso + + spice-widget: keypress-delay set by env var + +2015-06-15 Marc-André Lureau + + Prepare for 0.29 release + + channel: check too long password + Make sure that the password length is under the maximum lenght. If not + report it as an authentication failure with an adapted message. + +2015-06-15 Pavel Grunt + + configure: Try gstreamer audio backend if pulse is not available + Disable audio if no backend is available and configure is used with + the option '--with-audio=auto' + +2015-06-09 Victor Toso + + webdav: keep phodav requirements inside USE_PHODAV + Commit 33d4016228798108250b0ef9173f2c4c719a5065 uses + g_output_stream_write_all_async/finish which is on gio 2.44 version. + This breaks the build on older systems even if --disable-webdav is used. + + Using #USE_PHODAV to wrap those functions that will not be called + without --enable-webdav. + +2015-06-09 Fabiano Fidêncio + + spice-widget: Do not update display when resize-guest is disabled + Updating the display causes weird behaviors in virt-viewer, like + re-resizing to a previous monitor config when, after changing the + display resolution (through System > PReferences > Displays). the agent + reconnects. + It is not perfect yet, because when the agent reconnects the guest + resizes to the previous config and switch to the proper one, but this + seems more like an agent bug than a spice-gtk one. + +2015-06-08 Marc-André Lureau + + channel: use class private handlers field + Since spice-gtk requires glib 2.28, we can now fix a small FIXME. + + Since G_TYPE_CLASS_GET_PRIVATE is a bit expensive, it's still worth to + cache it in klass->priv. However, there is no good place I can think of + to put this. (channel_class_init() is called only once, and not per + each subclass) + + Move gtk/ -> src/ + For historical reasons, the code was placed under gtk/ subdirectory. + If it was always bugging you, bug no more! + + TODO: update + Remove outdated items: + - ChannelBaseAudio?, + - GDI backend wouldn't work well with scaling (moved to fdo bug) + + Fix fdo link + +2015-06-08 Pavel Grunt + + usb-device-manager: Avoid error when compiling with --disable-usbredir + +2015-06-05 Marc-André Lureau + + usb: remove useless assignments + The struct is g_new0() already. + + win-usb: try to connect to usbclerk during init + Fail early during initialization if the usbclerk service can't be + reached. + + This changes the current behaviour that would retry to connect to + usbclerk every time to perform an operation. Now, it will try each time + the UsbDeviceManager is initialized. + + usb: do not return GError on programmer pre-condition checks + Use regular g_return precondition checks. + + win-usb: remove useless function + + usb: misc code formatting + + usb: call win_usb_driver_new() during initable_init() + Throw an error when initialization failed. + + usb: use SPICE_CLIENT_ERROR_ prefix + To be consistent with GLib idioms, the code should use a common prefix for errors. + + usb: unref the device when it is no longer needed + The current code unref() the device too early, it must be unref + after it is no longer needed. + + win-usb: get rid of status code return in async ops + + win-usb: throw an error if reply.status == 0 + + usb: use win-usb uninstall_finish() + + win-usb: rename async functions + + win-usb: introduce a spice_win_usb_driver_op_finish + We want the exported functions to follow the gio async idom. Currently, + both install() and uninstall() are paired with install_finish(). In the + following patch we introduce uninstall_async() uninstall_finish() using + that common internal op_finish() function. Then we correctly pair + associated async/finish() calls. + + usb: remove useless declaration + +2015-06-05 Victor Toso + + tests: add test to check for zombie GSources + Using g_pollable_input_stream_create_source to generage several dummy + GSources in order to check if giopipe sets all of them to be dispatched. + + This test check for zombie GSources during a write_all/read_chunk + operation. + + tests: add test to concurrent write to pipe + Concurrent write is not supported and should fail. The GIO error is + G_IO_ERROR_PENDING + + tests: pipe using _write_all_async function + + tests: remove read8_cb to use generic read_cb + Both functions are basic the same so let's keep the generic one. + + webdav: write all buffer to client webdav + Client's webdav can request less data (8192) then the amount sent by + guest's webdav. Using g_output_stream_write_all_async in order to avoid + losing data. + + giopipe: don't fail on create_source + PipeInputStream and PipeOutputStream should not fail when creating + GPollableStream source as this currently does not work with default + write_all and read_all functions; + + In order to avoid creating zombie GSource in create_source of both + PipeInputStream and PipeOutputStream, we track all created GSources and + set them to be dispatched when data is available to read/write. It is + worth to mention that concurrent write/read is not possible with current + giopipe and only the last created GSource will read the data as it is + dispatched first. + +2015-06-03 Pavel Grunt + + session: Enable proxy when requested + Disabling the proxy avoids usage of GProxyResolver to determine + the necessary proxy protocol and to do the proxy negotiation. + +2015-05-28 Marc-André Lureau + + session: disable default socket proxy + GSocketClient uses the system proxy by default, and it may end up using + the system HTTP proxy with bad results if CONNECT is not + supported. spice-gtk uses it's own SPICE_PROXY instead, and doesn't rely + on GSocketClient default proxy but GProxyAddress instead. Disabling the + default proxy solve a wrong proxy from being used. + + It may be worth to revisit this change if GSocketClient can be told to + ignore proxies that are not eligible for Spice connections. (HTTP could + be though, in which case it would be a user configuration issue) + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1040679 + +2015-05-21 Benjamin Gilbert + + Drop expansions of removed CFLAGS/LIBS variables + +2015-05-21 Marc-André Lureau + + iopipe: fix leak of streams + g_simple_io_stream_new() do not steal references from us, unref the + streams to avoid the leaks. + + Leak found by Victor Toso. + + ==30787== 2,808 (648 direct, 2,160 indirect) bytes in 9 blocks are definitely lost in loss record 479 of 482 + ==30787== at 0x93AEBFD: g_type_create_instance (gtype.c:1849) + ==30787== by 0x939128A: g_object_new_internal (gobject.c:1774) + ==30787== by 0x9392AA0: g_object_newv (gobject.c:1921) + ==30787== by 0x939338B: g_object_new (gobject.c:1614) + ==30787== by 0x403B30: make_gio_pipe (giopipe.c:441) + ==30787== by 0x403C8E: spice_make_pipe (giopipe.c:465) + ==30787== by 0x4029B5: fixture_set_up (pipe.c:42) + ==30787== by 0x9844EC8: test_case_run (gtestutils.c:2123) + ==30787== by 0x9844EC8: g_test_run_suite_internal (gtestutils.c:2185) + ==30787== by 0x984509A: g_test_run_suite_internal (gtestutils.c:2196) + ==30787== by 0x98453FA: g_test_run_suite (gtestutils.c:2249) + ==30787== by 0x9845430: g_test_run (gtestutils.c:1553) + ==30787== by 0x402012: main (pipe.c:312) + +2015-05-12 Marc-André Lureau + + spicy: remove useless signal handlers + There is no strong reason to have signal handlers in spicy (a test + tool). Clean quit can be achieved through the File/Quit menu. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1197175 + +2015-05-12 Lukas Venhoda + + spice-gtk: Fixed build when using audio gstreamer + Commit No. 63bf00275769928850113b4df205df08d6303b45 changed number of + arguments of function playback_stop(), and didn't change call of this + function on line 628. + + This would break building when using --with-audio=gstreamer + +2015-05-07 Marc-André Lureau + + webdav: check g_output_stream_write_all() return value + Check g_output_stream_write_all() return value to silence a coverity + CHECKED_RETURN warning + + usb: channel-new handler to be after default handlers + Client usually connect to channel-new to connect their + handlers, such as open-fd. + + The usbmanager channel-new handler will call channel_connect() on usbredir + channels, which may call open-fd. + + However, open-fd can be emitted before the client had a chance to + connect their handlers (from the channel-new callback). + + Connecting after the default handler solves this case. + + Fixes: + https://bugzilla.gnome.org/show_bug.cgi?id=748665 + + session: do not attempt to open_host if session changed + Since channel can become session-less, let's check they still have the + expected session when running the open-host idle. + + audio: stop playback on channel destroyed + Ensure playback is stopped when the channel is destroyed. + + audio: use swapped channel handler for stop + We are going to reuse playback_stop() in following commit. + + record: do not crash after record is stopped + If spice_record_send_data() after a reset, last_frame is NULL and memcpy + will crash. Check if the recording was started if last_frame != NULL + instead. + + Program received signal SIGSEGV, Segmentation fault. + __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:204 + 204 vmovdqa %ymm0, (%rdi) + (gdb) bt + #0 __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:204 + #1 0x00007ffff44f57b5 in spice_record_send_data (channel=0x1228640, data=0x7fff9ad0f000, bytes=960, time=0) at channel-record.c:349 + #2 0x00007ffff45162f0 in stream_read_callback (s=0xad8c00, length=960, data=) at spice-pulse.c:485 + #3 0x00007ffff2ea0c76 in pstream_memblock_callback (p=, channel=, offset=0, seek=PA_SEEK_RELATIVE, chunk=0x7fffffffcf70, userdata=0x11e71c0) at pulse/context.c:411 + #4 0x00007fffe8da8b4f in do_read (p=p@entry=0x123a050, re=re@entry=0x123a1d0) at pulsecore/pstream.c:906 + #5 0x00007fffe8daae87 in do_pstream_read_write (p=0x123a050) at pulsecore/pstream.c:193 + #6 0x00007ffff30e1bea in dispatch_func (source=0x1111e50, callback=, userdata=) at pulse/glib-mainloop.c:584 + #7 0x00007fffed76b93b in g_main_dispatch (context=0x816ea0) at gmain.c:3122 + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1215343 + + playback: do not set mm time when session-less + Channels do not hold a strong reference on the session (because session + can be recycled after disconnect), do not print a warning if the channel + is session-less when updating the delay. + + audio: emit stop when the channels are reset + Ensure a hint is given to the client that the channel is reset. + + Unfortunately, since the handle may be asynchronous due to coroutine, + the channel functions should be tolerant to a playback/record calls + functions when the channel is stopped. + + audio: channel-new handler to be after default handlers + Client usually connect to channel-new to connect their + handlers, such as open-fd. + + The audio channel-new handler will call channel_connect() on audio + channels, which may call open-fd. + + However, open-fd can be emitted before the client had a chance to + connect their handlers (from the channel-new callback). + + Connecting after the default handler solves this case. + + Fixes: + https://bugzilla.gnome.org/show_bug.cgi?id=747649 + +2015-04-30 Victor Toso + + spice-pulse: compatibility with old pulse version + The commit 37ba949716ebf441110330 breaks compatibility with old versions + of libpulse as the volume and mute data in pa_source_output_info were + available only from version 1.0.0 onwards. Using other API function for + this which does not relay on audio per stream. + + spice-pulse: GSimpleAsyncResult compatibility + Avoid breaking build with glib older then 2.32 which is when + g_simple_async_result_set_check_cancellable was introduced. + + glib-compat: add G_SOURCE_REMOVE G_SOURCE_CONTINUE + +2015-04-28 Fabiano Fidêncio + + session: Get the lock modifiers from GdkKeymap + A cleaner way to get the lock modifiers, without depend on the + platform/backend used (as X or Wayland), is get them through GdkKeymap + (and its _get{caps,num,scroll}_lock_state() functions). + Unfortunately, get_scroll_lock_state() will only be present for Gtk+ + 3.18.0 and when it becomes the minimal required version we can easily + drop the old code. + +2015-04-24 Victor Toso + + agent: sync guest audio with client values + Functions to sync volume and mute value when necessary. In this patch, + only one sync is allowed after agent connect. + + Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1012868 + + audio: spice-gstaudio implements async volume-info + Gstaudio rely on sink/src elements to get the volume/mute. + (e.g. pulsesink and pulsesrc, the values are updated by PulseAudio + itself when requested) + + audio: spice-pulse implement async volume-info + In case of volume-sync between client and guest, we request volume-info + from the availables streams and if the stream is not available we rely + on ext-stream-restore. + + By using ext-stream-restore we can get the last stream data of the + application that is stored by PulseAudio. + + Related: https://bugzilla.redhat.com/show_bug.cgi?id=1012868 + + audio: spice-audio with get mute and volume + Async functions to be implemented by spice-gstaudio and spice-pulse to + get the updated volume and mute values for playback and record stream. + + Related: https://bugzilla.redhat.com/show_bug.cgi?id=1012868 + + Update spice-common submodule + This includes volume synchronization protocol; + +2015-04-24 Pavel Grunt + + spice-widget: Do not invalidate cursor when display is not ready + spice_display_get_scaling() gives wrong x, y coordinates and scaling + when the display is not ready. The wrong values cause runtime + warnings when disabling a virt-viewer's window: + Gtk-CRITICAL **: gtk_widget_queue_draw_area: assertion 'width >= 0' failed + +2015-04-16 Christophe Fergeau + + Fix GSocketAddress leak in proxy_lookup_ready() + g_proxy_address_new() returns a new GProxyAddress, so we must unref it + when no longer needed. + + This fixes: + + ==6481== 234 (48 direct, 186 indirect) bytes in 1 blocks are definitely lost in loss record 10,062 of 10, + ==6481== at 0x31FF230A58: g_type_create_instance (gtype.c:1849) + ==6481== by 0x31FF21501A: g_object_new_internal (gobject.c:1774) + ==6481== by 0x31FF216EB4: g_object_new_valist (gobject.c:2033) + ==6481== by 0x31FF217220: g_object_new (gobject.c:1617) + ==6481== by 0x3D4386F33A: g_proxy_address_new (gproxyaddress.c:325) + ==6481== by 0x5717440: proxy_lookup_ready (spice-session.c:2011) + ==6481== by 0x3D43885082: g_task_return_now (gtask.c:1088) + ==6481== by 0x3D438850B8: complete_in_idle_cb (gtask.c:1102) + ==6481== by 0x31FEE4A0B9: g_main_dispatch (gmain.c:3122) + ==6481== by 0x31FEE4A0B9: g_main_context_dispatch (gmain.c:3737) + ==6481== by 0x31FEE4A44F: g_main_context_iterate.isra.29 (gmain.c:3808) + ==6481== by 0x31FEE4A771: g_main_loop_run (gmain.c:4002) + ==6481== by 0x363AC06CC4: gtk_main (in /usr/lib64/libgtk-3.so.0.1600.1) + +2015-04-15 Jonathon Jongsma + + Make update-symbol-files work when builddir != srcdir + rewrite the update-symbol-files rule to use dependencies and automatic + variables ($^) so that VPATH will allow make to find these files in the + srcdir as well as the builddir. + +2015-04-14 Marc-André Lureau + + channel: HUP is not an error condition + On local UNIX sockets, calling close() in the server side will result in + a HUP condition on client side. Since this is not an error, but a normal + termination, let's ignore it. + + A clean shutdown would involve a new message to tell the client to first + close its end, in order to avoid the HUP. That way the client could + distinguish normal termination from unexpected ones. That's a possible + future minor enhancement (it seems it would only work with UNIX socket + though) + + G_IO_IN seemed to be a leftover, it is left here but shouldn't be + required. + + https://bugs.freedesktop.org/show_bug.cgi?id=90016 + + channel: reset c->has_error when connected + Whenever the channel socket is connected, c->has_error should be reset. + Until now, only the regular open_host() case was reset, but client + client provided fd must also reset the error state. + + It should be safe to move it after the "connected" label, since the + ssl code doesn't need c->has_error. + + https://bugzilla.redhat.com/show_bug.cgi?id=1211063 + +2015-04-01 Victor Toso + + audio: keep compatibility with old pulse version + The commit 9ef68ecd1fd11dea626628 breaks compatibility with old versions + of libpulse as the source_output functions were available from version + 1.0.0 onwards. + +2015-03-27 Pavel Grunt + + channel-smartcard: Add missing USE_SMARTCARD checks + In order to enable build without smartcard support + +2015-03-25 Marc-André Lureau + + smartcard: add reader and cards on channel up + The smartcard manager reports reader/card events on insertion and + removal. If a smartcard channel is created after those events, the + channel state will not be in sync with the current reader/card state. + Sync the state when the channel is up. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=1205171 + + smartcard: connect object signal handlers with spice helper + The smartcard manager may outlive the smartcard channels. Make sure the + channel handlers are disconnected when the channel is free by using + spice_g_signal_connect_object() helper. This fixes crashes when + dispatching smartcard events on deleted channels. + + Related bug: + https://bugzilla.redhat.com/show_bug.cgi?id=1205171 + +2015-03-23 Victor Toso + + audio: use stream functions for pulse source + The functions pa_context_set_source_output_mute/volume are specifically + to change source stream volume/mute. + I changed the warnings to be compatible to sink_input ones; + +2015-03-23 Christophe Fergeau + + session: Tone down warning on TLS-only connections + 315c1a5 "session: Add more debugging logs" causes a g_warning() to be + shown when attempting a TLS connection without specifying a non-TLS + port. + This commit makes the message more explicit, and switches it from being + a warning to being a debug message. + +2015-03-12 Pavel Grunt + + channel-usbredir: Do not stop event listening if SpiceSession does not exist + Avoids Segfault when closing the connection just after the usb device redirection. + +2015-03-04 Marc-André Lureau + + build-sys: fix out-of-tree build from tarball + There are generated files in build directory too. Fixes: + + CC util.o + In file included from ../../tests/session.c:3:0: + ../../gtk/spice-session.h:24:30: fatal error: spice-glib-enums.h: + No such file or directory #include "spice-glib-enums.h" + + Prepare v0.28 release + +2015-03-03 Marc-André Lureau + + build-sys: fix required libsoup version for webdav support + + Revert spice-common change + Commit 85ed268 shouldn't have change spice-common, my bad + + session: bind path and read-only to webdav server + Keep the server property in sync with the session properties + + session: add share-dir-ro property + Add a property to specify if share folder access is read-only. + + webdav: use a pipe to connect to server + Instead of listening on TCP sockets, and proxying connections there, + make the webdav server accept new connections from stream. The streams + are user-space GIOStream pipe, one side is connected to the Spice webdav + channel muxer/demuxer, the other side is a SoupSocket client. + + This makes the server not exposed any local public access, avoid the + need for server threads, or proxying the connections through system + sockets. + + Use libphodav-2 (breaks webdav server temporarily) + This change breaks webdav server, since libphodav-2 no longer + set up a TCP service running in a thread. It's up to the client + to decide how best to accept and handle new connections. + + This commits remove all the hacks related to proxying the incoming + connections to a TCP socket, and protected with a magic sequence. + + The following commit will use GIOStream pipes to handle each client + connections. + + Add GIOStream-based pipe + This code creates a pipe between 2 GIOStream, the input side read from + the peer output side, and vice-versa. + + In the following patches, this will avoid the socket communication + to exchange with the embedded webdav server. + + glib-2.0 >= 2.43.90 because GSimpleIOStream dependency. + +2015-02-27 Victor Toso + + tests: add spice-session test + Checking if URIs are being parsed and generated correctly. + + session: accept argument in URI without value + The examples below should be considered valid URIs: + + e.g: spice://localhost?port=5900&tls-port= + e.g: spice://localhost?tls-port=&port=5900 + + This patch deals with arguments with empty value; + +2015-02-23 Pavel Grunt + + vncdisplaykeymap: Use XkbGetMap and XkbGetNames instead of XkbGetKeyboard + XkbGetKeyboard does not work in XWayland (bfo#89240). + + Fixes https://bugs.freedesktop.org/show_bug.cgi?id=89105 + +2015-02-18 Marc-André Lureau + + session: reset connection_id on switch-host + The server expects no connection_id during link time, in order to + realize a full reconnection. + + The alternative would be to assume that the destination server has the + exact same channels and attempt to recreate and to reconnect them one by + one. However, if the destination is slightly different (say, + configuration or order of channels differs), this will likely fail. It's + best to start with a new session without prior knowledge. + + channel: remove unused ChannelClass::channel_disconnect() + This virtual method turns out to be unnecessary anymore, and + was never override. channel_reset() is enough. + + channel: set c->has_error to finish coroutine + It's unnecessary to call channel_disconnect() to finish the coroutine + and disconnect. Use c->has_error instead, like the rest of channel error + code. + + Call channel_reset() directly when finishing coroutine + channel_disconnect() virtual method isn't overloaded by any + channel, and can be replaced by the equivalent channel_reset() + when finishing the coroutine. + + channel: reset migration state when calling channel_reset() + channel_reset() is called in channel_disconnect(). We can just move that + state change in channel_reset() in order to get rid of + channel_disconnect(). + + channel: use exisiting reconnection code when switching + Switching for migration reason is similar to a reconnection during + initial connection. + + A notable difference is that new code path doesn't schedule a + delayed_unref callback. This is fine since the channel is still running + and delayed_unref is mainly used for signaling disconnections and none + should be emitted when switching. + + channel: reset channel state to unconnected + After coroutine has exited, reset channel state to unconnected, + this allows recycling a channel for reconnection, even in "normal" + disconnect/reconnect cases. + + channel: remove useless precondition + This precondition isn't useful, since the channel is already + dereferenced before, and I've never seen an idle callback not passing + the user_data correctly. + + channel: emit close event when coroutine has finished + Move signaling of closed channel after the coroutine has exited in + delayed_unref callback, similarly to error events, so it's easier to + schedule reconnect since coroutine has terminated. + +2015-02-16 Javier Celaya + + channel-port: Remove dependency cycle + channel-port.h includes spice-client.h, that includes channel-webdav.h, + that includes channel-port.h again. It's enough if channel-port.h + includes spice-channel.h + + Without this change, if one tries to build a source file which only + includes spice-port.h, the build fails with: + + In file included from /usr/include/spice-client-glib-2.0/spice-client.h:46:0, + from /usr/include/spice-client-glib-2.0/channel-port.h:22, + from ./port.c:1: + /usr/include/spice-client-glib-2.0/channel-webdav.h:44:5: error: unknown type name 'SpicePortChannel' + SpicePortChannel parent; + ^ + /usr/include/spice-client-glib-2.0/channel-webdav.h:58:5: error: unknown type name 'SpicePortChannelClass' + SpicePortChannelClass parent_class; + +2015-02-16 Pavel Grunt + + widget: Do not draw cursor if widget is not realized + Silences the runtime warning in virt-viewer and gnome-boxes (bgo#744432): + Gtk-CRITICAL **: gtk_widget_queue_draw_area: assertion 'width >= 0' failed + +2015-02-12 Pavel Grunt + + widget: Send keys to guest when keyboard grab is released + Keys should be sent to the guest if the widget has the focus even + when the keyboard grab is released. + +2015-02-06 Marc-André Lureau + + webdav: fix checking for shared directory property + Trivial fix for 6163828e8cb15d539c80cc3f0bfb5008be9b2247: + Channel should be created if the shared-dir property is set. + +2015-02-06 Benjamin Gilbert + + Don't build libspice-client-gtk if configured --without-gtk + libspice-client-glib is useful as a client library on platforms that + don't support GTK. + +2015-02-06 Christophe Fergeau + + Update git submodule + This fixes build with mingw as well as lz4 support: + + 3aad79d LZ4: Do not include arpa/inet.h in Windows builds + 9287e53 LZ4: Add support for 24bit pixman surfaces + d167e2e LZ4: Fix the row alignment when it is not on a 32bit boundary + f76fc28 LZ4: Decode the image format from the stream + 83c0d64 LZ4: Adjust reading the top_down flag + 6049db4 LZ4: Fix output buffer size + ac26fd7 Remove redundant #if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) + 062bf67 Remove unused 'invers' arg from canvas_get_* + 619b995 common: fix build with mingw + 862b9b1 build-sys: Move pixman check to m4 macro + 137b1a5 build-sys: Move opengl check to m4 macro + f9e0a64 build-sys: Move opus check to m4 macro + dd57d05 build-sys: Move celt check to m4 macro + fb3fe22 build-sys: Move smartcard check to m4 macro + df74a17 build-sys: Move posix checks to a separate m4 macro + 2f1ba3b build-sys: Add fallback for AS_VAR_APPEND + 2195369 build-sys: Small cleanup of AM_CPPFLAGS + ed873a9 build-sys: Remove unused WITH_SMARTCARD conditional + 2da14b6 build-sys: Remove unused win32 check + 5bfa9ca build-sys: Remove unused X check + 268d3e3 Remove unused header file + +2015-01-29 Christophe Fergeau + + Don't set SpiceSession::cmain twice during migration + During migration, migrate_connect() ends with: + spice_session_set_main_channel(mig->session, + migrate_channel_connect(mig, SPICE_CHANNEL_MAIN, 0)); + + migrate_channel_connect() calls spice_channel_new() which will create a + new SpiceMainChannel instance. + spice_channel_constructed() will be called during this instanciation, + which will call spice_session_channel_new(), which will set + SpiceSession::cmain for SpiceMainChannel instances. + + When calling spice_session_set_main_channel(), SpiceSession::cmain will + thus already be set, which causes a runtime warning as + spice_session_set_main_channel() has a precondition checking that + SpiceSession::cmain is not set already. + + This commit removes the call to spice_session_set_main_channel() from + migrate_connect() as this call is not doing anything more than the call + to migrate_channel_connect(). + + Remove runtime warning when setting a NULL shared-dir + Now that the webdav channel can cope with a NULL shared dir (by not + creating the webdav server), we no longer need to reject NULL shared + directories with a warning. + + This fixes part of https://bugzilla.redhat.com/show_bug.cgi?id=1175721 + + webdav: Cope with NULL SpiceSession::shared-dir + shared-dir default value is + g_get_user_special_dir(G_USER_DIRECTORY_PUBLIC_SHARE) + which can be NULL (for example if ~/.config/user-dirs.dirs does not + exist). + This commit makes sure we don't create a PhodavServer when this occurs + + display: Fix 'exisiting' typo in debug log + + display: s/dropin/dropping in debug message + + session: Add more debugging logs + Initial SPICE connection can sometimes fail without clear indications + where/how it failed. This commit adds more debug logs/more accurate logs + in order to help narrow down such issues. + + display: Improve DisplayChannel::num_drops_on_arive name + 'arive' has a typo, and 'num_drops_on_receive' is clearer. + + Use macro to swap data in spice_session_start_migrating() + spice_session_start_migrating() swaps connection details between 2 + SpiceSession instances. Instead of doing it manually, use a macro to do + it for us. + +2015-01-29 Pavel Grunt + + desktop-integration: check owner of bus name + It avoids calling D-Bus methods when the bus name + "org.gnome.SessionManager" does not exist. + + Silences: + GSpice-WARNING **: Error calling 'org.gnome.SessionManager.Inhibit': GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.SessionManager was not provided by any .service files + +2015-01-27 Marc-André Lureau + + spicy: deal with spice+unix:// URI + + session: teach spice_uri_create() about UNIX path + + session: prettify query parameters + Use & as parameters separators, this is more usual. Remove + trailing one, no further parameters are useful anyway. + + session: return allocated string from spice_uri_create() + This allows more flexible string building. + + session: parse spice+unix:// URI + + session: connect to UNIX path + + session: add unix-path property + + channel: reset connection state on error + Fix regression introduced in 6b475802, to permit reconnection on error, + the channel state must be < STATE_CONNECTING. Since the error is + reported after coroutine exits and channel is reset, the state can be + modified before throwing the error now. + + channel: reset tls state when client calls connect + The channel TLS state is kept during disconnection and reset, for + automatic reconnection and migrations reasons. However, when + spice_channel_connect() is called by client, it should first try + non-TLS connection. + + channel: delay event report to after coroutine exit + Move to a common place error reporting, after the coroutine exits. + +2015-01-23 Pavel Grunt + + spice-widget: Don't return early from focus_in_event when widget is not realized + Otherwise SpiceDisplay might not get the keyboard grab. + It also silence GSpice-CRITICAL on focus out event: + GSpice-CRITICAL **: spice_gtk_session_request_auto_usbredir: assertion 's->auto_usbredir_reqs > 0' failed + +2015-01-16 Zeeshan Ali (Khattak) + + session: Improved docs for spice_session_connect() + Make it clear that users of this function must provide additional + sockets for individual channels. + +2015-01-08 Benjamin Gilbert + + inputs: Correct documentation of scancode arguments + AT scancodes" implies AT set 2, but the SPICE protocol expects + AT set 1. spice-gtk additionally expects a mangled version of + set 1 scancodes, which are then unmangled by spice_make_scancode() + +2015-01-06 Fabiano Fidêncio + + README: update gstreamer info + + nsis: drop gst-0.10 in favour of gst-1.0 + Based on Victor Toso's patch for virt-viewer: + https://git.fedorahosted.org/cgit/virt-viewer.git/commit/?id=3bbf1ded1cb01429d600b11035d5fb0d60bfe20b + + audio: drop gst-0.10 in favour of gst-1.0 + As gstreamer-1,0 support was introduced by commit d4d60c97 and + it works pretty much as gstreamer-0,10 used to work (tests were + made both on Linux and Windows clients), let's drop the old + gstreamer-0.10 support in favour of gstreamer-1.0. + +2014-12-22 Marc-André Lureau + + usbredir: prevent crash when calling without host + Quite annoyingly, usbredir doesn't have public functions arguments + preconditions, and will weirdly run the flush callback during + initialization. + + With 201a8c2 change, the channel state is kept as it is when calling + reset. This will result in the following crash that was avoided before + thanks to a precondition on the channel to be ready. Adding a further + precondition check on priv->host != NULL solves the following crash + during reset(): + + Program received signal SIGSEGV, Segmentation fault. + usbredirhost_write_guest_data (host=0x0) at usbredirhost.c:868 + 868 return + usbredirparser_do_write(host->parser); + (gdb) bt + #0 0x00007fffb2ed24d0 in usbredirhost_write_guest_data (host=0x0) at + #usbredirhost.c:868 + #1 0x00007fffc81d463b in + #usbredir_write_flush_callback (user_data=0x2d95250) at + #channel-usbredir.c:469 + #2 0x00007fffb2ed23f9 in usbredirhost_open_full (usb_ctx=0x2baba70, + #usb_dev_handle=0x0, log_func=, + #read_guest_data_func=0x7fffc81d482c , + #write_guest_data_func=0x7fffc81d4952 , + #flush_writes_func=0x7fffc81d45c3 , + #alloc_lock_func=0x7fffc81d49f1 , + #lock_func=0x7fffc81d4a41 , + #unlock_func=0x7fffc81d4a86 , + #free_lock_func=0x7fffc81d4acb , + #func_priv=0x2d95250, version=0x7fffc8283dcf "spice-gtk + #0.27.7-89db-dirty", verbose=4, flags=1) at usbredirhost.c:748 + #3 0x00007fffc81d3b22 in + #spice_usbredir_channel_set_context (channel=0x2d95250 + #[SpiceUsbredirChannel], context=0x2baba70) at channel-usbredir.c:212 + #4 0x00007fffc81d37a9 in spice_usbredir_channel_reset (c=0x2d95250 + #[SpiceUsbredirChannel], migrating=0) + at channel-usbredir.c:125 + #5 0x00007fffc81b7f8d in spice_channel_reset (channel=0x2d95250 + [SpiceUsbredirChannel], migrating=0) + at spice-channel.c:2688 + #6 0x00007fffc81b8057 in channel_disconnect (channel=0x2d95250 + [SpiceUsbredirChannel]) at spice-channel.c:2706 + #7 0x00007fffc81b7559 in + spice_channel_coroutine (data=0x2d95250) at spice-channel.c:2490 + +2014-12-16 Marc-André Lureau + + channel: clear channel error after auth error + When entered authentication details are wrong, spice-gtk will reset + channel error, which will result in the following warning: + + (remote-viewer:20753): GLib-WARNING **: GError set over the top of a + previous GError or uninitialized memory. + This indicates a bug in someone's code. You must ensure an error is NULL + before it's set. + + Clear channel error after reporting authentication error. + + channel: throw auth error when coroutine ends + It is common that clients attempt to reconnect during the + SPICE_CHANNEL_ERROR_AUTH callback. However, the channel must exit + the coroutine first before reconnection can happen. + + channel: introduce SPICE_CHANNEL_STATE_RECONNECTING + Add a new state that permits reconnection, because it's < CONNECTING. + It also simplifies some code by removing unneeded variables in + spice_channel_coroutine(): the channel.tls and session.protocol version + properties are already modified during initial connection steps. + + channel: do not enter channel iterate on early error + There is no need to enter channel_iterate() if we found an early + connection steps error. + + channel: factorize failed authentication + There are a few things that should be common to all wrong authentication + cases. Let's put them all in the same function. + + session: keep main channel on reconnect + For legacy reasons, spice-gtk should keep at least one channel in the + session when reconnecting (clients may decide that the session is + disconnected when all channels are gone). The most obvious is to + keep and reuse the main channel. + +2014-12-11 Marc-André Lureau + + Prepare 0.27 release + +2014-12-11 Marc-André Lureau + + docs: improvements for 0.27 release + +2014-12-06 Marc-André Lureau + + build-sys: update git.mk + +2014-12-03 Marc-André Lureau + + Fix build for glib < 2.32 + G_SOURCE_REMOVE was introduced in 2.32 + +2014-12-02 Javier Celaya + + Add LZ4 compression algorithm support. + - Use PKG_CHECK_MODULES to find liblz4. + - Set LZ4 display channel capability. + +2014-12-01 Marc-André Lureau + + usb: keep USB context alive as long as channels exist + It was assumed the session would remain alive as long as channel + existed, so USB context would be valid too. Now that channels + are removed from session, USB context may be destroyed before + channels. This produces invalid read/write on USB context. + Make sure the context is alive as long as USB channels are by + adding a reference on USB manager. + + ==6939== Invalid write of size 4 + ==6939== at 0x394B604482: libusb_set_debug (core.c:1850) + ==6939== by 0x3953A063D5: usbredirhost_open_full (usbredirhost.c:741) + ==6939== by 0x4EC7E2F: + spice_usbredir_channel_set_context (channel-usbredir.c:212) + ==6939== by 0x4EC7AB6: + spice_usbredir_channel_reset (channel-usbredir.c:125) + ==6939== by 0x4EACCDC: spice_channel_reset (spice-channel.c:2621) + ==6939== by 0x4EACDB4: channel_disconnect (spice-channel.c:2640) + ==6939== by 0x4EAC28F: spice_channel_coroutine (spice-channel.c:2423) + ==6939== by 0x4EE8B1C: coroutine_trampoline (coroutine_ucontext.c:63) + ==6939== by 0x4EE87D6: continuation_trampoline (continuation.c:55) + ==6939== by 0x3928247FEF: ??? (in /usr/lib64/libc-2.20.so) + ==6939== by 0x51E36FF: ??? (in + /usr/local/stow/spice-gtk/lib/libspice-client-glib-2.0.so.8.5.0) + ==6939== by 0xCF0C18F: ??? + ==6939== Address 0xff15f90 is 0 bytes inside a block of size 536 free'd + ==6939== at 0x4A07CE9: free (in + /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) + ==6939== by 0x394B606466: libusb_exit (core.c:2041) + ==6939== by 0x4ECC590: spice_usb_device_manager_finalize (usb-device-manager.c:371) + + usb: return early if channel is not usb + Return early if channel is not USB, replace: + + if (SPICE_IS_USBREDIR_CHANNEL(channel)) { + /* code */ + } + + with + + if (!SPICE_IS_USBREDIR_CHANNEL(channel)) + return; + + session: disconnect in idle + This is a workaround for existing clients such as virt-viewer that do + not hold a reference to their sessions when calling + spice_session_disconnect() and crash now that channels are removed from + session during the call. They expect disconnection events to be deferred + instead, let's defer actual disconnection to idle time for public + disconnect API for compatibility reasons (it is still recommended to fix + client code, for eventual future iterations) + + session: keep a reference on disconnect + It is idiomatic for client code to clean up its reference on channel + disconnection. Keeping a reference during disconnect helps solving + potential crashes if the session is unref'ed during callbacks. + + session: remove sticky disconnecting flag + This used to help prevent double-unref when channel were considered part + of the session as long as they lived. Now it shouldn't be required + anymore + + channel: deprecate spice_channel_destroy() + This function is somewhat useless, and dangerous since it is calling + g_object_unref() behind your back (although this is mentioned in the + doc, I consider this a bad practice). + + display: don't reschedule stream if disconnected from session + Avoid the following critical when a channel is disconnected with a + pending stream (the streams are cleared on channel reset, after + coroutine exit) + + (process:17188): GSpice-CRITICAL **: spice_session_get_mm_time: assertion 'session != NULL' failed + + #0 0x00007ffff71c24e5 in spice_session_get_mm_time (session=0x0) at spice-session.c:1999 + #1 0x00007ffff71d438c in display_stream_schedule (st=0xa33040) at channel-display.c:1014 + #2 0x00007ffff71d4a09 in display_stream_render (st=0xa33040, + st@entry=) at channel-display.c:1165 + #3 0x0000003e1944a553 in g_timeout_dispatch (source=0xad64e0, callback=, user_data=) at gmain.c:4520 + #4 0x0000003e19449aeb in g_main_context_dispatch (context=0x6a32b0) at gmain.c:3111 + #5 0x0000003e19449aeb in g_main_context_dispatch (context=context@entry=0x6a32b0) at gmain.c:3710 + #6 0x0000003e19449e88 in g_main_context_iterate (context=0x6a32b0, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3781 + #7 0x0000003e1944a1b2 in g_main_loop_run (loop=0x97e200) at gmain.c:3975 + #8 0x0000003e1c9ebb35 in gtk_main () at gtkmain.c:1207 + #9 0x0000000000430185 in main (argc=1, argv=0x7fffffffdcb8) at virt-viewer-main.c:119 + + session: remove channels on disconnect + A channel is considered to be part of a session as long as it is + alive. However, this model is problematic, since library user may hold + channel references, and thus the channel will remain in the + session. Calling spice_session_disconnect() several time will end up + calling spice_channel_destroy(), releasing references that aren't owned + by the session. This usually causes crashes, in particular with language + bindings that do not deal well with a library model where objects can't + be referenced at will. + + session: move SpiceSessionPrivate out of headers + Make sure none of the SpiceSessionPrivate fields are accessed directly anymore + + gtk: do not require glib session private fields + Use GObject object association for session helpers. + + GtkSession and DesktopIntegration are in the gtk library SpiceSession is + in glib one. So far we had the SessionPriv structure shared between the + two libraries, so they could fit their pointers there. But this is no + longer possible when moving the private structure in .c. We could add + more accessors, but they would need to be in public API, and this isn't + supposed to be accessed by API users. + + usb: move device manager initialization to session + Use session accessors to initialize the device manager. + Add missing session parameter check (public API). + + webdav: move initialization to session + Use session accessors to initialize the webdav server + + Rename display_channels_count/n_display_channels + + session: add and use internal accessors + Avoid dereferencing session private data directly, and use accessors + instead. + + session: set session for migration when connecting + + session: rename migration_copy/for_migration + + smartcard: use spice_session_is_for_migration() + + smartcard: do not initialize manager for migration session + The migration session is temporary and shouldn't interact with system. + + Add spice_session_is_for_migration() + + session: protect internal functions against invalid args + Make sure calling an internal session function returns with an error + when called with a NULL pointer. This will help channel code when + it is removed from session before being destructed. + + audio: move spice_audio_get() to session + + audio: add accessor to check if audio is enabled + +2014-12-01 Victor Toso + + audio: Avoid bad pipelines from gst_parse_launch + gst_parse_launch may return not NULL even when error is set. + This can lead to data loss when playing or recording audio. + + audio: new-sample callback must return GST_FLOW_OK + +2014-12-01 Marc-André Lureau + + build-sys: simplify autogen.sh + + build-sys: fix out-of-tree autofoo + +2014-11-30 Pavel Grunt + + Release keyboard grab using keyboard shortcut + This commit adds the ability to release the keyboard grab when + the release keys (ctrl+alt) are pressed and released. It allows + to use keyboard shortcuts (eg alt+tab, alt+f4) on the client. + + The keyboard is grabbed again when the release keys are pressed + and released or when the mouse moves. + + https://bugs.freedesktop.org/show_bug.cgi?id=85331 + +2014-11-27 Fabiano Fidêncio + + spice-widget: check whether the widget is realized in focus_in_event() + Returning early on focus_in_event(), when widget is not realized, avoids + segfault when running on Windows using GTK3. + + Program received signal SIGSEGV, Segmentation fault. + _gdk_windows_has_impl at gdkwindow.c:584 + bt + #0 _gdk_window_has_impl (window=window@entry=0x0) at gdkwindow.c:584 + #1 0x70f02821 in gdk_win32_window_get_handle (window=0x0) at + gdkwindow-win32.c:3459 + #2 0x00c759ef in update_display (display=0x1b18440) at + spice-widget.c:1297 + #3 0x00c77280 in focus_in_event (widget=0x1b18440, focus=0x1b02b68) at + spice-widget.c:1462 + #4 0x665727f5 in ?? () from C:\Program Files\VirtViewer + (GTK3)\bin\libgtk-3-0.dll + #5 0x00000000 in ?? () + +2014-11-24 Marc-André Lureau + + migration: delay switch host reconnect + The following critical happens on switch-host: + + (remote-viewer:4617): GSpice-CRITICAL **: channel_connect: assertion + 'c->sock == NULL' failed + + The critical happens since the main channel reset code calls + set_agent_connected(), which will yield to main loop, so reconnection + can't happen after calling spice_channel_disconnect(), and must wait + until the channel reset completes. + +2014-11-21 Marc-André Lureau + + migration: don't check socket error + During migration, the original socket is closed before the coroutine + finishes, so it's not guaranteed that c->sock will still be set when the + channel is in an error state in spice_channel_iterate(). + + coroutine: reference object when signaling + Before the signal is actually emitted, the channel may be + released. Let's keep a reference to the object during + the function time, to prevent the object from being destroyed before + calling g_signal_emit() or g_object_notify() in main context. + + migration: use spice_session_abort_migration() on error + Use a more complete method for the job + + migration: remove unnecessary reference + + migration: create the migration session earlier + The migration session creation may fail. Instead of delaying the session + creation to the main_connect() callback, do it directly from the message + handler context, to report failure early to server. + + migration: improve debug log + + migration: remove migration cleanup from dispose + The spice_session_disconnect() method now calls + spice_session_abort_migration(), so it is not necessary to do migration + cleanups in dispose anymore + + migration: set connecting state before fd request + During migration, the main channel coroutine initiating the process is + waiting for connection completion of all + channels. migrate_channel_event_cb() yields back to the main channel + coroutine once all channels have completed connection, or it will abort + migration for unexpected channel events, such as SPICE_CHANNEL_CLOSED + + If the migration is cancelled before connection completes, but the + channels state are still in the SPICE_CHANNEL_STATE_UNCONNECTED state, + no events will be emitted in channel_disconnect(), and the source + session main channel will remain frozen waiting for migration completion + or failure. + + Currently, for client-fd channels, the channel state remains UNCONNECTED + until the fd is provided. But if cancellation occurs, no channel events + are emitted and the source session is stuck. + + Before requesting the fd, set the channel state to connecting, so it + will emit an error if disconnect happens, and it will finish cancelling + the migration in source session main channel. + + migration: fail with client provided fd + Currently the fd request is done on the migration session, which is not + connected with the client session, so the client has no way to provide + fd for the migration. And the original and migration session ends up + stuck. Failing early seems the best for now. + + migration: set session migration during connect + Track the migration session earlier, so that disconnecting before + migration finished will abort and release it. + + migration: add "connecting" state + Add a new migration state to track early migration step, when migration + session is connecting to destination + + migration: abort migrate on disconnect + If the session has an ongoing migration, but it is disconnected, + abort it. + + migration: add a few more pre-conditions in migration code + Those preconditions help to figure out several issues related to + migration. + + usb: stop processing usb events on error + If libusb returned an error in the event loop, stop further event + handling. This avoid spinning in an error loop in error cases. + + audio: use weak references to channel + The audio channels are currently referenced and released on channel + close events. However, this event may not happen if the channel never + was connected. Keeping channels alive also prevent session from + finishing. + + By not holding the ref, the channel can go to dispose + when it is no longer needed, and the session can be disposed too. + + Add missing finalize chaining + Finalize should chain up to the finalize method of the parent class. + + Trivial fix. + + Remove obsolete TODO item + Tunnel are long obsoleted (did they ever work) + Remove it from TODO list. + + Pushed unreviewed as trivial + +2014-11-19 Fabiano Fidêncio + + usb-device: Expose libusb device + As we only can filter USB devices by their Classes and sometimes it is + not enough (eg: I do not want to have Keyboard and Mouse, but I want to + have Joysticks, being all of them part of HID Class), let's expose the + libusb device associated to the SpiceUsbDevice, so the applications can + have access to whatever information they need, directly from the libusb + device, to refine their filters. + +2014-11-19 Christophe Fergeau + + Really fix SndCodec leaks in handle_{playback,record}_start + The leak fix from commit 6729c341120f was actually not doing anything at + all as it was setting c->codec to NULL before trying to free it. It was + also not fixing the exact same leak in the record channel. + This commit addresses these 2 issues. + + Recheck clipboard size after modifying its data + SpiceGtkSession::clipboard_received_cb() starts by checking if the + clipboard is empty, or if the length of its data exceeds + 'max-clipboard-size'. + + Later in that function, the data is modified, and can be shortened + (removal of trailing '\0' or of '\r' for Windows -> linux copy and + paste), or enlarged (addition of '\r' for linux -> Windows c&p). + + This commit adds another check that the clipboard length is still valid + (non-0, and not bigger than 'max-clipboard-size') after making these + transformations. + + Fix empty clipboard check + SpiceGtkSession::clipboard_received_cb starts by checking if the + length of the X selection data is not 0. However, right after this check, + if gtk_selection_data_get_length() returned -1, it decides it got an + empty clipboard, sets the selection length to 0, and does not return + early. + This commit reworks the len == 0 / len == -1 checks to make sure we + always return early when we get no data from the clipboard. + +2014-11-04 Marc-André Lureau + + Draw server-side pointer when the session has the grab + If there are several SpiceDisplay widgets, only one will have the grab, + but the pointer may need to be drawn on another of the displays. We + thus need to track the grab status on SpiceSession, not just + per-display. + + This solves the following bug: + https://bugs.freedesktop.org/show_bug.cgi?id=38024 + + gtk-session: add pointer-grabbed property + Returns TRUE if the pointer is currently grabbed by this session. + + Add missing G_GNUC_INTERNAL + Trivial fix + +2014-10-31 Christophe Fergeau + + Drop glib < 2.28 support + With el6 now shipping glib 2.28, there is no very good reason to keep + support for older glib versions alive, especially as it will barely be + tested. + +2014-10-31 Victor Toso + + Add GStreamer 1.0 audio support + Based on Christophe Fergeau's patch. + To enable audio with GStreamer 1.0: --with-audio=gstreamer1 + + There is only a few changes between those versions, worth mentioning: + - audio capabilities "audio/x-raw,format=..." instead of + "audio/x-raw-int,..." + - appsink signal for new data changed from "new-buffer" to "new-sample" + +2014-10-30 Christophe Fergeau + + Always use #include "config.h" + gnulib 'make syntax-check' prohibits use of #ifdef HAVE_CONFIG_H so this + commit removes it from where it's used. It also makes sure we always use + the same syntax for including config.h (#include "config.h" VS #include + ) as a consistent way of doing that is expected. + + Remove spice-mime.xml/spicy.desktop + They were never translated from .in files to actual files, and now it's + clear we don't want to promote spicy as a first-class desktop + application. + + Fix "can not" typo in comment + + Remove redundant use of const + const guint16 const * has one extra 'const' which is removed by that + commit + + Remove trailing whitespace + + Remove blank lines at end of files + + Add missing (C) to Red Hat copyright line + gnulib's make syntax-check comes with a rule enforcing that Red Hat + copyright lines contain both "(C)" and "Copyright". + + Add quoting around AC_DEFINE* first argument + + build-sys: Don't use test -a/-o + They are not portable, it's recommended to use test && test or test || + test instead + +2014-10-30 Marc-André Lureau + + mailmap: add Dietmar Maurer + + build-sys: add some missing MAINTAINERCLEANFILES + + build-sys: generate gitignore in tests dir + + build-sys: change default libtool options + - disable-static: it's quite uncommon to use static build of gtk libraries + - win32-dll: the shared libs build cleanly for win32 already + +2014-10-29 Christophe Fergeau + + Regenerate symbol files with make update-symbol-files + Some symbols were manually added to these files not in the right place + (non-alphabetical order). This causes spurious diffs when trying to + compare these files with the ones make update-symbol-files would + generate. + This commit syncs these file with the ones which are autogenerated to + spot more easily differences between the file in git and the + autogenerated one. + + Tell ctags to ignore G_GNUC_CONST in declarations + Without that, it will fail to parse: + GType spice_uri_get_type(void) G_GNUC_CONST; + + Remove spice_gtk_session_sync_keyboard_modifiers from public headers + It's not meant to be exported as it's not listed in spice-gtk symbol map file. + + Add spice_session_get_proxy_uri to spice-glib-sym-file + It was only added to map-file. + + Update spice-common submodule + This picks up some warning fixes. + + Update NEWS + + Don't strip \0 from non-text clipboard data + Commit a8f2e2d added recomputation of the length of clipboard data to + strip the trailing \0 in order to avoid a Windows gtk+ bug. However it's + doing it too for non-text data, which causes issues when copying images + as they are very likely to contain \0 within their data. They will thus + be truncated. + + This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1154719 + + Reindent block of code in clipboard_received_cb + This is in preparation for fixing a regression in image copy&paste. This + commit only introduces a new (unused) block and reindent the + corresponding code, it can easily be reviewed with git show -w + +2014-10-29 Marc-André Lureau + + build-sys: make vapigen silent + + build-sys: clean-up generated vapi files + + build-sys: remove unnecessary BUILT_SOURCES rule + + build-sys: add extra dependencies on symbols files + Whenever the symbols files are modified, rebuild the library. + + build-sys: s/GLIB_VERSION/GLIB_SYMBOLS + +2014-10-27 Daniel P. Berrange + + Fix macro for checking spice version numbers + As it is for now, the micro number is never checked. + +2014-10-27 Marc-André Lureau + + gtk: hide cursor when ungrabbed + Let's avoid confusion of multiple pointers visible on the client + desktop: hide the guest pointer if the spice client doesn't have the + grab, display it again when the grab is taken back. + + gtk: keep cursor in the same place on ungrab + On ungrab, the transition from remote (server-side) cursor to host + cursor makes it jump somewhere else rather than staying at the same + place. Restore cursor position on ungrab to match with guest position. + + https://bugs.freedesktop.org/show_bug.cgi?id=85117 + +2014-10-23 Christophe Fergeau + + Fix SndCodec leak in playback_handle_start() + An audio SpiceChannel can get several times the 'start' message during + its lifetime. If received multiple times (for example when rebooting a + VM), this would lead to a SndCodec leak as reported by valgrind: + + ==7749== 27,036 (48 direct, 26,988 indirect) bytes in 1 blocks are definitely lost in loss record 11,418 of 11,440 + ==7749== at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) + ==7749== by 0x5772A9A: spice_malloc0 (mem.c:109) + ==7749== by 0x5772D42: spice_malloc0_n (mem.c:173) + ==7749== by 0x57FB3E2: snd_codec_create (snd_codec.c:267) + ==7749== by 0x573774C: playback_handle_start (channel-playback.c:380) + ==7749== by 0x5721E44: spice_channel_handle_msg (spice-channel.c:2859) + ==7749== by 0x571ECB3: spice_channel_recv_msg (spice-channel.c:1877) + ==7749== by 0x571F402: spice_channel_iterate_read (spice-channel.c:2114) + ==7749== by 0x571F614: spice_channel_iterate (spice-channel.c:2152) + ==7749== by 0x5720411: spice_channel_coroutine (spice-channel.c:2429) + ==7749== by 0x575CD3A: coroutine_trampoline (coroutine_ucontext.c:63) + ==7749== by 0x575C9F4: continuation_trampoline (continuation.c:55) + ==7749== by 0x3898E47FEF: ??? (in /usr/lib64/libc-2.20.so) + ==7749== by 0xAED547666C92C2FF: ??? + ==7749== by 0xFFEFFF92F: ??? + +2014-10-10 Cole Robinson + + m4: Update manywarnings from gnulib + Fixes these noisy errors on Fedora 21: + + gcc: warning: switch '-Wmudflap' is no longer supported + +2014-10-10 Fabiano Fidêncio + + Add support to handle username when connecting with SASL + Based on a patch from Dietmar Maurer + http://lists.freedesktop.org/archives/spice-devel/2013-October/015138.html + + Add errors related to the SASL auth + SPICE_CLIENT_ERROR_AUTH_* will be used to set more detailed errors + with respect to the main channel event SPICE_CHANNEL_ERROR_AUTH. + + Add missing doc for SPICE_CLIENT_USB* errors + +2014-10-10 Dietmar Maurer + + Add "username" property to SpiceSession + +2014-09-18 Christophe Fergeau + + Don't report IO error on clean guest shutdown + Since commit 9cf9ca434, spice_channel_iterate() will report a + SPICE_CHANNEL_ERROR_IO error to library users when + SpiceChannel::has_error is set. In particular, when the server side + closes its SPICE sockets because the VM is being shut down, an IO error + will get reported. Prior to this change, a channel-closed event was + reported on graceful VM shutdowns as there was + a g_socket_condition_check() guarding the emission of the IO error + signal. + + This commit readds the g_socket_condition_check() test, but only when + SpiceChannel::has_error is set. + + This fixes https://bugs.freedesktop.org/show_bug.cgi?id=83692 + +2014-09-18 Pavel Grunt + + Fix -Wsign-compare + +2014-09-18 Fabiano Fidêncio + + channel-main: allow transferring multiple files at once + Allow to drag and drop, from host to guest, more than one file at the + same time. + +2014-09-05 Christophe Fergeau + + win-usb: Initialize GError before using it + GError variables must be set to NULL before passing them to a function + which might set them. + This fixes the runtime warning reported in rhbz#1138195: + + (remote-viewer.exe:3896): GLib-WARNING **: GError set over the top of a + previous GError or uninitialized memory. + This indicates a bug in someone's code. You must ensure an error is NULL + before it's set. + The overwriting error message was: handle_dev_change: Error getting + device list from libusb: Other error [-99] + +2014-08-29 Marc-André Lureau + + xfer: send data message of size 0 for 0-size file + Make sure we send a xfer data message for 0-size files. + This avoid leaking file descriptiors in guest agent when + copying such files. + + Reported-by: Cody Chan + + https://bugzilla.redhat.com/show_bug.cgi?id=1135099 + +2014-08-28 Jonathon Jongsma + + Wait to send monitor config until agent caps are received + When the first display is disabled and the vdagent is restarted in the guest, + it sometimes becomes enabled. This appears to be caused by a race condition + when an agent becomes connected. When the agent becomes connected, virt-viewer + triggers a display update (spice_main_send_monitor_config()). This display + update happens in a timeout handler, but the timeout interval is set to 0 (so + it behaves basically like an idle handler). + + The race happens because spice_main_send_monitor_config() behaves slightly + differently depending on the agent's capabilities. And sometimes the idle + handler runs before the client and server have negotiated capabilities. In this + case, we have to assume that the server does not support sparse monitor + configurations. So instead of sending down an update where display #0 is off + and display #1 is WxH, we send down an update that only a single display: + display #0 is WxH. This results in the first display becoming enabled. + + To solve the issue, we wait until the agent negotiates capabilities + before sending the display configuration message. + + Resolves: rhbz#1043782, rhbz#1032923 + +2014-08-21 Marc-André Lureau + + win32: fix coroutine assertion when switching to TLS port + Since v0.21-35-gbaa51c5, there are some new coroutine preconditions. + + The winfiber implementation can reach, when the structure isn't cleared, + which happens when switching channel connection to TLS port and the + coroutine is recycled. + + CRITICAL **: coroutine_yieldto: assertion '!to->exited' failed + + In a near future, it would be nice to use the safer implementation + proposed for glib, see bgo#719362 (using a private copy) + +2014-08-13 Christophe Fergeau + + Use G_OS_WIN32 #define everywhere + Currently some parts of the windows specific code is checking for the + WIN32 define, and other parts are checking G_OS_WIN32. This commit uses + G_OS_WIN32 everywhere for consistency. + +2014-08-13 Cody Chan + + keyboard: wrong defined macro for WIN32 + On windows client, there's no effect for guest when + enabling CAPS_LOCK/NUM_LOCK/SCROLL_LOCK on + (because of the delay, guest may take the effect for several seconds). + There's a wrong defined macro, then is ALWAYS 0, + and the keyboard state of guest is synchronized with the state client + by spice_gtk_session_sync_keyboard_modifiers_for_channel(...). + +2014-08-13 Christophe Fergeau + + Fix 'loose' typo + + Fix build with automake 1.14 + When building a source file from a different directory, automake 1.14 + is warning that the automake option 'subdir-objects' must be used: + + automake: warnings are treated as errors + gtk/Makefile.am:218: warning: source file + '$(top_srcdir)/spice-common/common/sw_canvas.c' is in a subdirectory, + gtk/Makefile.am:218: but option 'subdir-objects' is disabled + automake: warning: possible forward-incompatibility. + automake: At least a source file is in a subdirectory, but the + 'subdir-objects' + automake: automake option hasn't been enabled. For now, the + corresponding output + automake: object file(s) will be placed in the top-level directory. + However, + automake: this behaviour will change in future Automake versions: they + will + automake: unconditionally cause object files to be placed in the same + subdirectory + automake: of the corresponding sources. + automake: You are advised to start using 'subdir-objects' option + throughout your + automake: project, to avoid future incompatibilities. + autoreconf: automake failed with exit status: 1 + + This causes the build to fail because we are also using the -Werror + automake option. + Updating the spice-common submodule to git master fixes part of this + issue as 7ea1cc5 'Fix generation of marshallers in VPATH builds' removed + directory references from some source files. + + This commit removes the references to + $(top_srcdir)/spice-common/common/sw_canvas.[ch] from gtk/Makefile.am. + At this point, automake subdir-objects support does not seem to cope + very well with source files which are not in relative subdirectories, + see http://mytestbed.net/issues/1327 + What is done instead is to add some local client_sw_canvas.[ch] files + which will include the needed files from spice-common with the + appropriate #define set (these sw_canvas.[ch] files are meant to be used + as templates). + + This fixes https://bugs.freedesktop.org/show_bug.cgi?id=67304 + + channel-display: Remove #ifdef SW_CANVAS_CACHE + It's unconditionnally defined at build time in the global CPP flags, so + the #ifdef SW_CANVAS_CACHE are always enabled and can be removed. + + Ensure '\0' is not part of text clipboard data + On Windows, with some versions of gtk+, GtkSelectionData::length + will include the final '\0'. + When a string with this trailing '\0' is pasted in some linux + applications, it will be pasted as or as an invisible character, + which is unwanted. + + This commit ensures the length we send to the agent does not + include any trailing '\0'. + + https://bugzilla.redhat.com/show_bug.cgi?id=1090122 + +2014-07-23 Marc-André Lureau + + Update spice-common + +2014-07-23 Fabiano Fidêncio + + Don't use _GET_PRIVATE all the time + Let's make use of the priv members in the structs, which are much much + faster. Also, to keep the type-safety, the SPICE_IS_* macros were added + in the public methods affected by this patch. + + Patch based on an old patch from Alexander Larsson (alexl@redhat.com). + + Prefer using g_malloc0()/g_free() + As we already depend on GLib, let's use g_{malloc,new}0() instead of the + standard malloc() or the spice_{malloc,new}*() and g_free() instead of + the standard free() when possible. + Memory allocated by other libraries using malloc() should still be freed + by free(). + As a side effect of the changes, we are muting a few warnings caught by + coverity. + + Fix "REVERSE_INULL" caught by coverity + + g_type_init() is deprecated in GLib 2.36 + +2014-07-07 Marc-André Lureau + + session: prefix proxy lookup errors + Proxy errors are already reported with G_IO_ERROR_PROXY messages, + however proxy name lookup error can be more detailed. + + https://bugzilla.redhat.com/show_bug.cgi?id=1115986 + +2014-06-17 Marc-André Lureau + + proxy: use http proxy by default if no scheme given + SPICE_PROXY used to accept URI without scheme, falling back on + http/3128. This is a regression introduced with 5dcab09ac + +2014-06-10 Marc-André Lureau + + Remove coroutine trampolines + Use va_list instead of an ugly trampoline hack + + usbredir: don't use emit_main_context() for non-signal code + The following patch deprecates the signal helper code + +2014-05-22 Marc-André Lureau + + README: add vala-tools build-dep + +2014-05-22 Tiziano Müller + + Add missing GIO_LIBS to libspice-client-glibs + If spice-gtk is built without PHODAV, libgio is missing from the list of + libraries to link against, causing undefined symbols for all gio functions. + +2014-05-21 Tiziano Müller + + Do not depend on libsoup directly + The libsoup-dependency is not directly used but comes in as a dependency + of phodav and phodav has libsoup correctly recorded in its pkg-config + file. + + Introduce --enable/disable-webdav option + This makes the phodav dependency configureable. + And name it after the corresponding channel. + +2014-05-20 Marc-André Lureau + + Revert "clipboard: prevent reentering main loop if main channel is busy" + This change broke primary clipboard copying from remote to client, on win32. + + There is a pending ::clipboard-grab emission, so the channel is not + idle, and it will handle emission and resume in the inner loop without + issue. We should really handle this situation with care though, and the + best would be to teach gtk+ to do async clipboard request. + + This reverts commit e3efa8cec51045d87a14a7e4f921c24ad5caffb1. + +2014-05-15 Marc-André Lureau + + clipboard: check that clipboard request does not belong to remote + Check clipboard owner, to avoid cyclic dependency of clipboard requests. + + clipboard: prevent reentering main loop if main channel is busy + The main channel must be idle to avoid entering the nested loop, + or it will never reach the condition to leave it. + + This should not happen. It can happen currently when the remote sends a + clipboard request while the clipboard is grabbed by the remote. In this + case, while the clipboard-request signal is emitted by main channel, the + clipboard_get() loop is entered, but the main coroutine will not be + woken up to proceed with the request, the main channel will remain + "frozen" and it won't be possible to leave cleanly from the inner loop. + The application appears to be frozen, because it can't quit properly. + + Related to: + https://bugzilla.redhat.com/show_bug.cgi?id=1083489 + +2014-04-29 Christophe Fergeau + + Include glib-compat.h in spice-option.c + Commit 8c89485 added a call to g_clear_pointer(). + +2014-04-24 Marc-André Lureau + + option: check that default ca-file exists + Don't set default ca-file path if the file doesn't exists. + +2014-04-23 Marc-André Lureau + + option: use more portable default ca-file path + If no CA path is given, a default one is set. Use g_build_filename() to + set a more portable and valid default path. + +2014-04-17 Christophe Fergeau + + Fix leak in spice_gtk_session_sync_keyboard_modifiers() + The list of channels returned by spice_session_get_channels() + must be freed after use. + +2014-04-15 Marc-André Lureau + + display: signal primary-destroy when clearing all surfaces + When destroying the primary surface, we need to signal it, since + listeners might be referencing the data pointer. Currently, this only + happens during channel finalize(). + + This could help with rhbz#1082555. + + gtk-session: always sync modifiers for client events + The channel state is not synchronous. + + It may happen that we want to set and unset quickly a modifier, but the + guest modifier state hasn't been updated yet, and will still be seen as + unset, preventing the last unset change. + + gtk-session: s/g_debug/CHANNEL_DEBUG + +2014-04-15 Christophe Fergeau + + Include gtk-compat.h in spice-gtk-session.c + GDK_IS_X11_DISPLAY is not available on gtk+ 2.x, but it already has a + fallback definition in gtk-compat.h + + Gather gtk+ compatibility code in a single file + There are gtk+ version checks in several source files to add + compatibility implementations of gtk3 functions not available + in gtk2. This commit gathers all of them in a gtk-compat.h header, + similar to what is done for glib-compat.h + + Add compat implementation of g_queue_free_full() + This was introduced in glib 2.32 and the webdav channel uses it. + +2014-04-08 Christophe Fergeau + + Use correct printf format modifier for gssize + This fixes this warning/error: + + channel-webdav.c: In function 'demux_to_client': + channel-webdav.c:318:5: error: format '%ld' expects argument of type 'long + int', but argument 5 has type 'gssize' [-Werror=format=] + CHANNEL_DEBUG(self, "pushing %ld to client %p", size, client); + + Add man page + Spice-GTK provides SPICE-specific command line options. This man page + describes these options as well as the format of SPICE URIs. + +2014-04-03 Jonathon Jongsma + + Use GdkKeymap to listen for keyboard modifier changes + Connect to the GdkKeymap::state-changed signal to detect when the client + keyboard modifiers have changed. This keeps the client and the guest in sync + even when the SpiceDisplay widget isn't focused. New values are only sent down + to the guest if the new value is different than the current value. + + Ensure keyboard modifiers are synchronized properly + In certain circumstances, the keyboard modifiers get out-of-sync between the + guest and the client. This is easy to reproduce with the following steps: + - launch virt-viewer with a guest that is not running + - start the guest + - while guest is booting, enable CAPS LOCK on the client + - after guest finishes booting, it will set its modifiers to a default value + (e.g. numlock on, capslock off) + - now capslock is OFF in the guest, but ON in the client + - toggle caps lock + - now capslock is ON in the guest, but OFF in the client + + This moves the responsibility for synchronizing client and guest modifiers into + SpiceGtkSession. It can't be handled easily within the SpiceDisplay widget since + there can be multiple display widgets for each inputs channel. + + A new function (spice_gtk_session_sync_keyboard_modifiers()) was added so that + synchronization can be triggered manually if desired. But it also registers a + signal handler for the InputsChannel::inputs-modifiers signal to detect when the + guest has changed its modifiers. The signal handler simply overrides the guests + modifiers and sets them back to the value from the client. + +2014-04-02 Marc-André Lureau + + Update NEWS for v0.25 + + Make phodav an optional external dependency + Now that upstream provides a stable/versioned API, it will be + easier to deal with than with submodules. + + build-sys: re-organize summary to show major info first + + build-sys: add missing soup subst + +2014-03-31 Jonathon Jongsma + + Fix missing SPICE_GTK_MICRO_VERSION value + configure.ac tries to assign a default value of 0 to the micro version if it's + empty, but the shell variable assignemnt doesn't work because there's whitespace + around the '=' sign. + + This results in SPICE_GTK_MICRO_VERSION being defined to (), which causes a + compilation failure in files that include it. + +2014-03-25 Marc-André Lureau + + Update NEWS for v0.24 + + Update phodav + +2014-03-25 Christophe Fergeau + + Advertise SASL cap from client + A client setting this capability indicates to the server that it's able + to handle SASL authentication, and it also indicates that if SASL is + to be used for authentication, then it won't expect a valid 'pub_key' field + in SpiceLinkReply. + + The reason for making guarantees about not looking at the pub_key field is + that its presence and size is hardcoded in the protocol, but in some + hardened setups (using fips mode), generating a RSA 1024 bit key as + expected is forbidden and fails. With this new capability, the server + knows the client will be able to handle SASL if needed, and can skip + the generation of the key altogether. This means that on the setups + described above, SASL authentication has to be used. + +2014-03-20 Marc-André Lureau + + webdav: use some more explicit names + Address Alon's review from + http://lists.freedesktop.org/archives/spice-devel/2014-March/016383.html + +2014-03-19 Marc-André Lureau + + Start NEWS file + + session: add shared-dir property and option + Allow to specify the shared directory from the command line, or at + runtime via properties. (still default to xdg public share, if none + specified) + + Add webdav channel + See spice-common for protocol details. phodav, a webdav server library, + is imported thanks to a submodule, until this project has a stable API + and releases. + + The webdav channel is reponsible for handling port events and + multiplexing the request streams. Extra care has been made to avoid + blocking and to enable some fairness between concurrent streams, however + this has been particularly tricky and is likely to have some issues + left. + + The webdav server is run in a seperate thread, using libsoup. The client + communication is done via a local tcp socket, but protected to only + accept local connection and with a pretty strong password. + + The home directory is exported for the remote to browse, which seems to + be a sensible default atm. + +2014-03-18 Christophe Fergeau + + mingw64: Fix gssize printf-format warnings + When building with mingw64, several warnings about using the wrong format + specifier for gssize/gsize occur similar to: + + win-usb-dev.c: In function 'g_udev_client_list_devices': + win-usb-dev.c:145:21: error: format '%i' expects argument of type 'int', but argument 7 has type 'gssize' [-Werror=format=] + name, errstr, rc); + + This commit makes use of the G_GSIZE_FORMAT/G_GSSIZE_FORMAT macros provided + by glib to silence these warnings. + + I've checked that this does not introduce new warnings on linux and mingw32 + builds. + +2014-03-14 Marc-André Lureau + + Fix spice_display_get_pixbuf() with offset area + Fix screenshot of secondary displays, with an area position != (0,0). + + This has never been working correctly since the surface display "area" + was introducted in: + + commit e3bb7b1cfd162fcb8943e9d582dab43eeec6ce41 + Author: Marc-André Lureau + Date: Tue Jun 12 19:24:47 2012 +0200 + + display: learn to restrict display to an area + + https://bugzilla.redhat.com/show_bug.cgi?id=1029761 + + Silence some gcc warnings + cc1: warnings being treated as errors + spice-uri.c: In function ‘spice_uri_parse’: + spice-uri.c:105: error: ‘saveptr’ may be used uninitialized in this + function [-Wuninitialized] + spice-uri.c:105: error: ‘saveptr2’ may be used uninitialized in this + function [-Wuninitialized] + +2014-03-13 Christophe Fergeau + + sasl: Rework memory handling in spice_channel_perform_auth_sasl() + While looking at the SASL code, I noticed some memory leaks in error paths. + This commit adds a cleanup: block to free some of the memory dynamically + allocated in that function, and remove the corresponding g_free() from + the regular code flow. This should ensure that both the regular path + and the error paths free the same memory. + + This fixes at least this 'mechlist' leak which I got during regular SASL + PLAIN authentication: + ==3452== 6 bytes in 1 blocks are definitely lost in loss record 140 of 11,706 + ==3452== at 0x4A0645D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.s + ==3452== by 0x35BAC4EE6E: g_malloc (gmem.c:104) + ==3452== by 0x5BF7CAA: spice_channel_perform_auth_sasl (spice-channel.c:1440) + ==3452== by 0x5BF9033: spice_channel_recv_link_msg (spice-channel.c:1727) + ==3452== by 0x5BFAECD: spice_channel_coroutine (spice-channel.c:2348) + ==3452== by 0x5C35D6D: coroutine_trampoline (coroutine_ucontext.c:63) + ==3452== by 0x5C35A1B: continuation_trampoline (continuation.c:51) + ==3452== by 0x31342479BF: ??? (in /usr/lib64/libc-2.18.so) + ==3452== by 0x75F2940591224CFF: ??? + ==3452== by 0xE756E5F: ??? + ==3452== by 0xE7589BF: ??? + ==3452== by 0xFFEFFF78F: ??? + ==3452== by 0x5BFCD92: g_io_wait_helper (gio-coroutine.c:43) + = + + Make sure config.h is included first in all .c files + This is recommended by autoconf documentation + http://nondot.org/sabre/Mirrored/autoconf-2.12/autoconf_3.html#SEC15 + and some #defines in config.h can change what happens in system headers, + so config.h has to be included first. + + The only file which does not get this treatment is + gtk/spice-client-gtk-module.c as this breaks the build on gtk+2: + + CC SpiceClientGtk_la-spice-client-gtk-module.lo + In file included from /usr/include/python2.7/pyconfig.h:6:0, + from /usr/include/python2.7/Python.h:8, + from /usr/include/pygtk-2.0/pygobject.h:5, + from spice-client-gtk-module.c:20: + /usr/include/python2.7/pyconfig-64.h:1182:0: error: "_POSIX_C_SOURCE" redefined [-Werror] + #define _POSIX_C_SOURCE 200112L + ^ + In file included from /usr/include/limits.h:25:0, + from /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/limits.h:168, + from /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/syslimits.h:7, + from /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/limits.h:34, + from /usr/lib64/glib-2.0/include/glibconfig.h:11, + from /usr/include/glib-2.0/glib/gtypes.h:34, + from /usr/include/glib-2.0/glib/galloca.h:34, + from /usr/include/glib-2.0/glib.h:32, + from /usr/include/glib-2.0/gobject/gbinding.h:30, + from /usr/include/glib-2.0/glib-object.h:25, + from ./glib-compat.h:24, + from ../config.h:201, + from spice-client-gtk-module.c:18: + /usr/include/features.h:228:0: note: this is the location of the previous definition + # define _POSIX_C_SOURCE 200809L + ^ + cc1: all warnings being treated as errors + +2014-03-10 Christophe Fergeau + + build-sys: Fix setting of SPICE_GTK_MICRO_VERSION + After e124a3b2e which added the SPICE_GTK_CHECK_VERSION macro, a non-fatal + './configure: line 15251: x24: command not found' appears in configure + output. This is because [ ] is not interpreted as the 'test' command by + autoconf, but is rather used as a way to quote configure.ac content. + This commit replaces the use of [] with a more typical AS_IF. + +2014-02-27 Christophe Fergeau + + Add missing #include "glib-compat.h" + wocky-http-proxy.c and vmcstream.c make use of functions that were + not available in glib 2.26 so we need fallback for them through + glib-compat.h or spice-gtk won't build with older glibs. + +2014-02-25 Marc-André Lureau + + display: fix crash when releasing primary surface + Since 1fcaaa15f8aca362f9e6afc87fb43cfbccf6ff62, display_surface is + allocated using gslice. However MSG_DISPLAY_MODE handler didn't allocate + using GSlice. This can eventually lead to a crash when freeing, such as: + + Thread no. 1 (6 frames) + #2 g_slice_free1 at gslice.c:1097 + #3 iter_remove_or_steal at ghash.c:787 + #4 clear_surfaces at /lib64/libspice-client-glib-2.0.so.8 + #5 spice_display_channel_finalize at + /lib64/libspice-client-glib-2.0.so.8 + #7 spice_channel_delayed_unref at /lib64/libspice-client-glib-2.0.so.8 + #12 gtk_main at gtkmain.c:1158 + + https://bugzilla.redhat.com/show_bug.cgi?id=1069546 + +2014-02-24 Marc-André Lureau + + Add a SPICE_GTK_CHECK_VERSION macro + +2014-02-21 Marc-André Lureau + + spice-common: revert last change + + session: add spice_session_get_proxy_uri() + Learn to return the currently configured proxy, to allow + client to tweak parameters, such as username and password. + + channel: add spice_channel_get_error() + Add a function to retrieve the last GError from a channel, this may be + useful to provide additional error details to the client. + + Make SpiceURI a public API + Generalize a little bit SpiceProxy to allow easy URI manipulation by + clients. + + channel: talk to giostream instead of gsocket + + channel: simplify has error code + Get rid of a superflous g_socket_condition_check(). + + openssl: learn to handle a new kind of BIO based on GIOStream + Although reusing BIO_new_socket() once again is a hack, it seems + to be the easiest way... The proper solution is certainly to start + using GTls instead, but that will require a glib 2.28 dep bump. + + Fill g_proxy_address_new() with protocol, user and password + This way, the call might eventually support more proxy and + authentication. + + http-proxy: add https proxy + This will require glib 2.28 for GTls support, atm + + spice-proxy: parse https protocol + + http-proxy: specify Basic scheme + Or Squid will fail with: + WARNING: Unsupported or unconfigured/inactive proxy-auth scheme + + proxy: parse user and pass from uri + + proxy: add user and pass properties + + proxy: split uri with : in only 2 parts + We want just host:port here. + + compat: add strtok_r fallback + The following Spice proxy URI parsing code makes use of it, but it is + not available on Windows + + Origin: + http://git.videolan.org/gitweb.cgi/vlc.git/?p=vlc.git;a=blob;f=compat/strtok_r.c + + misc: indent wocky proxy with 2-spaces + + misc: make warning more explicit + + Add SpiceVMC GIOStream + This allows to use conveniently GIOStream APIs without caring about + coroutine and Spice messages details. + + channel: add spice_vmc_write_async() + Refactor port code to create a private GIO async function that can send + SPICE_MSGC_SPICEVMC_DATA message over any channel. + +2014-02-20 Christophe Fergeau + + build-sys: Don't build tests when not building static libs + The tests rely on static linking in order to get access to symbols which + are not exported in spice-gtk shared libraries. When build of static + libraries is disabled with --disable-static, we should not attempt to build + the tests as this will result in link errors. + +2014-02-10 Christophe Fergeau + + Don't attempt to send 0 scancode when releasing keys + When releasing all keys, we send a key release for scancode in the + key_state array, including the very first element with scancode 0. + send_key() complain when the scancode is 0, so make sure we don't call it + for this first element. + + This fixes a + (remote-viewer:25548): GSpice-CRITICAL **: send_key: assertion 'scancode != 0' failed + warning when starting remote-viewer windowed, and then switching to another + desktop client-side using ctrl+alt+arrow. + +2014-02-10 Marc-André Lureau + + Release v0.23 + +2014-02-10 Ryan Lortie + + utils tests: fix sign comparison problem + This test compares a guint8 and a gchar with '==' which fails when comparing + 240 to -16, even though these are the same byte value. Add an explicit + 'guchar' cast to correct the problem. + + https://bugs.freedesktop.org/show_bug.cgi?id=74754 + +2014-02-07 Marc-André Lureau + + session: don't track open_host_idle source id + In all cases, when the coroutine is resumed, the idle source has been + running and thus will be removed. Doing it a second time results in the + wrong source being removed or an invalid source warning. + + spicy: do not flush and disconnect all kind of ports + Some ports may want to live a bit longer, such as following webdav. + + port: send opened a port-event signal on init + If the port is already opened, emit a "opened" port-event on init. This + simplifies user code to only handle port events. + + test: fix a few compiler warnings + util.c: In function 'test_set_bit': + util.c:131:13: warning: pointer targets in initialization differ in signedness [-Wpointer-sign] + + Add GDBus version of dbus-glib code + + Narrow dbus-glib code, to fit other implementation easily + + dbus: remove priv->dbus_conn + It's only needed once, and it is better to group with rest of dbus-glib + code. + + build-sys: detect GDBus + + misc: sed -i -e 's/USE_DBUS/USE_DBUS_GLIB/g' + +2014-01-07 Christophe Fergeau + + Use local GError in spice_convert_newlines() + spice_convert_newlines() declares a local 'err' GError but never uses it as + the function directly uses the 'error' variable passed as an argument. + Use 'err' throughout the function instead of the 'error' argument as this + looks like what was intended. + This fixes this coverity warning: + + Error: DEADCODE (CWE-561): [#def144] + spice-gtk-0.22.9-fb3d/spice-gtk3-0.22.9/gtk/spice-util.c:318: assignment: Assigning: "err" = "NULL". + spice-gtk-0.22.9-fb3d/spice-gtk3-0.22.9/gtk/spice-util.c:364: null: At condition "err", the value of "err" must be NULL. + spice-gtk-0.22.9-fb3d/spice-gtk3-0.22.9/gtk/spice-util.c:364: dead_error_condition: The condition "err" cannot be true. + spice-gtk-0.22.9-fb3d/spice-gtk3-0.22.9/gtk/spice-util.c:365: dead_error_begin: Execution cannot reach this statement "g_propagate_error(error, err);". + +2014-01-03 Christophe Fergeau + + controller: Don't call g_type_init() in test with newer glib + g_type_init() is deprecated, calling it on newer glib causes a compile-time + warning. + + controller: Add missing #ifdef WIN32 in test + The spicec_pid variable is only used in a #ifdef WIN32 block, but it was + unconditionnally declared/initialized. This causes a gcc warning. + + controller: Avoid out of string bound accesses in test + When computing the amount of data to send for static strings, the test + program is confusing sizeof() which returns the size of the string + including the trailing '\0' and strlen() which returns the size of the + string without the trailing '\0'. + This causes attempts to access one byte past the string. + This fixes this coverity warning: + Error: OVERRUN (CWE-119): [#def44] + spice-gtk-0.20/spice-gtk-0.20/gtk/controller/test.c:258: + overrun-buffer-arg: Overrunning array ""main,inputs,playback"" of 21 bytes + by passing it to a function which accesses it at byte offset 21 using + argument "22UL". + spice-gtk-0.20/spice-gtk-0.20/gtk/controller/test.c:101:5: + access_dbuff_in_call: Calling "memcpy(void * restrict, void const * + restrict, size_t)" indexes array "data" with index "data_size". + + cursor: Avoid potential sign extension issue + When doing arithmetic operations on the uint16_t cursor width and height + with integer constants, the result of the operation will be of type 'int' + as the integer constant as type 'int'. + There are 2 places which assign the result of such an operation to + an (unsigned 64 bit)) size_t variable. This means that if width/height are + big enough, the int -> size_t conversion would cause a sign extension to + happen, which is unwanted as we are only manipulating positive values. + + This commit explicitly mark the constants with the correct unsigned type. + This fixes this kind of coverity warnings: + + spice-gtk-0.20/spice-gtk-0.20/gtk/channel-cursor.c:388: sign_extension: + Suspicious implicit sign extension: "hdr->height" with type "unsigned + short" (16 bits, unsigned) is promoted in "4 * hdr->width * hdr->height" to + type "int" (32 bits, signed), then sign-extended to type "unsigned long" + (64 bits, unsigned). If "4 * hdr->width * hdr->height" is greater than + 0x7FFFFFFF, the upper bits of the result will all be 1. + +2014-01-02 Jeremy White + + Add support for the Opus codec. + + Don't emit start signals if codec creation fails. + + Use the new snd_codec interface to process encoded audio. + +2013-12-12 David Jaša + + Use TLS version 1.0 or better + When creating a TLS socket, both spice-server and spice-gtk currently + call SSL_CTX_new(TLSv1_method()). The TLSv1_method() function set the + protocol version to TLS 1.0 exclusively. The correct way to support + multiple protocol versions is to call SSLv23_method() in spite of its + scary name. This method will enable all SSL/TLS protocol versions. The + protocol suite may be further narrowed down by setting respective + SSL_OP_NO_ options of SSL context. This possibility is + used in this patch in order to block use of SSLv3 that is enabled by + default in openssl for client sockets as of now but spice has never used + it. + +2013-12-09 Marc-André Lureau + + coroutine: add missing glib.h include + +2013-12-03 Marc-André Lureau + + gtk: fix giscan warnings, add missing signal doc + GISCAN SpiceClientGLib-2.0.gir + channel-main.c:633: Warning: SpiceClientGLib: incorrect number of + parameters in comment block, parameter annotations will be ignored. + channel-main.c:672: Warning: SpiceClientGLib: incorrect number of + parameters in comment block, parameter annotations will be ignored. + channel-main.c:716: Warning: SpiceClientGLib: incorrect number of + parameters in comment block, parameter annotations will be ignored. + channel-main.c:757: Warning: SpiceClientGLib: incorrect number of + parameters in comment block, parameter annotations will be ignored. + channel-display.c:367: Warning: SpiceClientGLib: incorrect number of + parameters in comment block, parameter annotations will be ignored. + GICOMP SpiceClientGLib-2.0.gir + + Pushed unreviewed under trivial rule. + +2013-11-27 Marc-André Lureau + + Release v0.22 + v0.22 + ===== + + - improve inverted cursor support + - use system-wide trust certificate store + - make sasl support work with other method than MD5 + - fix some clipboard crasher, limit clipboard size + - fix various regressions: + usbredir, alt-tab on win32, palette crash, agent notification, old + protocol support, sasl ending crash, gthread coroutine crash, close + sockets on migration, pulse backend crash + - fix a few memory leaks + - build-sys improvements + + build-sys: bump spice-glib version + new symbols in spice-glib, bump before release + + continuation: fix "fortify" crash + Since 0508f586, errno.h is included above #undef _FORTIFY_SOURCE. + + But it must be placed above system headers to take effect + + *** longjmp causes uninitialized stack frame ***: + /home/jwhite/xfer/spice/bin/spicy terminated + ======= Backtrace: ========= + /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7ffff48dc2a7] + /lib/x86_64-linux-gnu/libc.so.6(+0xef239)[0x7ffff48dc239] + /lib/x86_64-linux-gnu/libc.so.6(__longjmp_chk+0x33)[0x7ffff48dc1a3] + /home/jwhite/xfer/spice/lib/libspice-client-glib-2.0.so.8(+0x49761)[0x7ffff78f1761] + /home/jwhite/xfer/spice/lib/libspice-client-glib-2.0.so.8(+0x499a4)[0x7ffff78f19a4] + /home/jwhite/xfer/spice/lib/libspice-client-glib-2.0.so.8(+0x1bae7)[0x7ffff78c3ae7] + /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_context_dispatch+0x135)[0x7ffff505f355] + /lib/x86_64-linux-gnu/libglib-2.0.so.0(+0x4a688)[0x7ffff505f688] + /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_loop_run+0x72)[0x7ffff505fa82] + /home/jwhite/xfer/spice/bin/spicy[0x4054aa] + /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7ffff480bead] + /home/jwhite/xfer/spice/bin/spicy[0x405679] + +2013-11-26 Marc-André Lureau + + pulse: do not abort on corking no stream + There is no guarantee that a stream actually exist when min-latency + change is notified. + + Check that there is an actual stream before calling cork(). All callers + where previously checking that stream existed. Add a pre-condition to + verify argument and spot that error is from spice-gtk itself. + + Fixes the following crash: + #1 0x0000003c12e34105 in abort () at abort.c:92 + #2 0x0000003c2c223180 in pa_stream_is_corked (s=0x0) at + pulse/stream.c:2536 + #3 0x0000003c2c648cb7 in stream_cork (pulse=, + s=0x7fbb38, with_flush=0) at spice-pulse.c:227 + #4 0x0000003c2c649989 in playback_min_latency_changed (object=, pspec=, data=0x7fbad0) at + spice-pulse.c:674 + + https://bugzilla.redhat.com/show_bug.cgi?id=1032785 + +2013-11-22 Marc-André Lureau + + channel: swap channel GSocketConnection on migration + When migration completes, unrefing the new connection leads to original + GSocket pending refs, and thus the sockets stay in CLOSE_WAIT. + + This is a regression from 8029bd0 where GSocketConnection is kept around + to satisfy old glib. + + https://bugzilla.redhat.com/show_bug.cgi?id=1024501 + + This will also probably fix: + https://bugzilla.redhat.com/show_bug.cgi?id=952375 + +2013-11-21 dietmar@proxmox.com + + Fix SASL for mechanism using WANT_CLIENT_FIRST + Current code works with DIGEST-MD5, but not with PLAIN. + + In particular, when using PLAIN, sasl_client_start() returns SASL_OK, which + should not be an error in spite of vague/confusing upstream documentation + about this: + http://asg.andrew.cmu.edu/archive/message.php?mailbox=archive.cyrus-sasl&msg=10104 + +2013-11-20 Marc-André Lureau + + main: fix recent main_channel_reset() warning + Fix wrong warning added in 0704147d. + + (lt-spicy:17511): + GSpice-WARNING **: (channel-main.c:415):spice_main_channel_reset: + runtime check failed: (c->agent_connected == FALSE) + + coroutine: make gthread coroutine pass tests + The coroutine entry() return value must be passed via the caller->data, + since coroutine_swap() returns from->data. (this is needed because + coroutine_swap() argument is used both to return from entry() or to send + data to a running coroutine) + + When leaving a coroutine, clear its caller. + + Return correct coroutine_self() before other coroutine are initialized. + + tests: add some coroutine tests + + coroutine: replace IN_MAIN_CONTEXT macro + Use a nicer function, with correct prefix. + Remove extra "context" from function name + + coroutine: error out on OOM or impossible conditions + Take an approach similar to gthreads, which are considered as low + level/must work features by glib, which aborts on failures. + + channel: get rid of connection_id, available from session + + channel: remove useless desc != NULL check + spice_channel_type_to_string() does not return NULL + +2013-11-20 Christophe Fergeau + + Fix 'monitors' leak in update_monitor_area() + This function has an early return where we fail to unref the 'monitors' + array. + +2013-11-19 Marc-André Lureau + + main: send max-clipboard to agent + Send configured max-clipboard size to the agent, after receiving agent + capabilities. + + See also spice-protocol patch description: + http://lists.freedesktop.org/archives/spice-devel/2013-November/015254.html + + main: simplify usage of VD_AGENT_HAS_CAPABILITY + Introduce a helper function test_agent_cap() to clear the code a + little bit. + + main: use self for main channel variable + This simplifies the following commit which uses even more + SPICE_MAIN_CHANNEL macro, and makes the code unnecessarily heavy. + + Add SPICE_MAX_CLIPBOARD environment variable + Allow to easily override default max-clipboard value with environment + variable. + + Block sending clipboard data > max-clipboard + Attempt to send very large clipboard data may easy cause OOM + abort, either in gdk - some patch are proposed to improve the situation, + or in spice-gtk itself. + + Let's have a property that blocks unreasonably big clipboard data from + being processed (by default 100mb). Users willing to send larger data + can use the send basic drag-drop send file instead, or tweak the + property value. + +2013-11-19 Christophe Fergeau + + Use system-wide trust certificate store + Currently, spice-gtk will look in $HOME/.spicec/spice_truststore.pem + by default for its trust certificate store (to verify the certificates + used during SPICE TLS connections). + However, these days, progress is under-way to have a system-wide + certificate store [1]. + In order to use it, we only need to call SSL_CTX_set_default_verify_paths() + and it will automatically use the shared system CA store if the distro + is properly setup. + We only try to use that store if there was no user-provided CA file to use, + or if we failed to load it. + + [1] https://fedoraproject.org/wiki/Features/SharedSystemCertificates + + build-sys: Add real autodetection of python + configure help text says that by default python will be used automatically + if appropriate, however this only means that on !windows and !gtk3, we will + force build of the python bindings, and fail if any needed package to build + them is missing. + + This commit improves on the current checks so that when autodetecting + python, if a package is missing then build of the bindings is silently + disabled rather than failing. + + build-sys: Re-enable building of python bindings by default + Commit daa4ece tried to disable building of python bindings on Windows by + default, but in doing so, it also disabled building of python bindings by + default when we are building neither for Windows nor for gtk3. + + build-sys: Fix invalid 'test' syntax in configure.ac + test ... -o test ... is not a valid shell construct, change it to + test ... || test ... as this is more portable than test ... -o ... + + This was causing a warning when running configure. + +2013-11-18 Christophe Fergeau + + Fix leak of mmapped memory when cc_init() fails + + Check coroutine_init() return value + coroutine_init() can fail, but spice-channel.c was not checking its return + value, which could lead to some crashes if coroutine_init() failed and we + then try to use coroutine_yieldto() + +2013-11-18 Daniel P. Berrange + + Free coroutine stack when releasing coroutine + The coroutine_init function mmap's a stack for the + ucontext coroutine, but nothing ever munmaps it. + + Abort if mmap of coroutine stack fails + If we fail to mmap the stack, abort the processs rather + than returning an error. This is standard practice in + glib apps, and the caller was not checking the + coroutine_init() return code leading to memory corruption. + +2013-11-18 Christophe Fergeau + + Fix IN_MAIN_CONTEXT when using coroutine=gthread + The IN_MAIN_CONTEXT macro checks coroutine_self()->caller against NULL to + decide whether we are in the main context or not. However, this is an + implementation detail of the ucontext coroutine implementation, in the + gthread implementation, coroutine_self()->caller will be non-NULL even in + the main context. + + This commit introduces a coroutine_is_main_context() method which each + coroutine backend implements. It turns out it can be implemented the same + way for each backend. + + Fix crash on remote-viewer startup with gthread coroutine + g_object_notify_main_context() was recently changed to automatically + detect whether we are running in the main context or not, and SpiceSession + is now using g_object_notify_main_context(). + + In order to achieve that, IN_MAIN_CONTEXT is used, but it's not safe + to be used before coroutine_init() is called. IN_MAIN_CONTEXT expands to + (coroutine_self()->caller == NULL), but coroutine_self() will be NULL when + using gthreads for the coroutine implementation until coroutine_init() has + been called. + + Before coroutine_init() has been called, we'll always be running in the + main context, so we can just add a check for coroutine_self() != NULL to + IN_MAIN_CONTEXT to solve that issue. + +2013-11-18 Marc-André Lureau + + coroutine: fix current coroutine + When leaving a coroutine, it swaps back to where it came from, not to + the leader/main coroutine. + + coroutine: add some preconditions + +2013-11-07 Jonathon Jongsma + + Guarantee that 'uuid' property is notified after connection + This creates a synchronization point and allows API users to rely on the fact + that they'll always get a UUID notification before all of the channels are + created. + + Make sure property notifications are done in the main context + Modify g_object_notify_main_conetxt() to work whether it's called from the main + context or a coroutine context. Change object notify calls in SpiceSession to + use g_object_notify_main_context() instead of g_object_notify(). + + Revert "Add ability to get SpiceDisplay resolution" + This reverts commit a285e0187d15ad650f6524f3811072fa55b20617. + + This API was not actually needed for what I intended to use it for. So revert + for now. We can always add it back if necessary in the future. + + Conflicts: + gtk/spice-widget.c + +2013-11-06 Marc-André Lureau + + display: blank surface on creation + In theory, zero-ing the surface shouldn't be necessary, as only + invalidated/painted region should be shown. However, this results in + less artifacts on resolution changes (probably some regions are painted, + but with masks, blend, copy etc), in particular on console after VM + reboot. + +2013-11-04 Marc-André Lureau + + widget: add since tag for spice_display_get_monitor_config() + +2013-11-04 Jonathon Jongsma + + SpiceDisplay: validate 'self' argument for public API + Add defensive g_return[_val]_if_fail(SPICE_IS_DISPLAY()) to all public API + + Add ability to get SpiceDisplay resolution + Add spice_display_get_monitor_config() to get the current configuration of the + display. + +2013-11-04 Marc-André Lureau + + Fix spice-common submodule, my bad + +2013-11-03 Marc-André Lureau + + util: document spice_uuid_to_string + +2013-11-01 Marc-André Lureau + + util: do not overwrite G_MESSAGES_DEBUG=all + glib log handler only check for a single 'all' value, mixing it with + other domains name will disable 'all' messages. + +2013-10-29 Jonathon Jongsma + + Export spice_uuid_to_string() properly + Update map-file and spice-glib-sym-file + + Expose spice_uuid_to_string() as public API + SpiceSeession has a 'uuid' property that is a byte array, but clients often need + the uuid in string format (for writing to disk, etc). Rather than having each + client re-implement this, expose the utility function as public API in + spice-gtk. + +2013-10-19 Alon Levy + + channel-cursor: mono cursors edge highlighting + Fix 998529, mono (invert) cursors not visible on a black background, by doing + simple edge detection on the cursor (this is done once when the cursor + is changed and then cached, cursors are 32x32 generally) and thus having + a cursor with contrast on both dark and light backgrounds. + + When (if) GDK gets invert cursor support (wayland?) then we can just use + the cursor as is. Until then X doesn't provide any way I see of solving + this otherwise. The end result was tested with the I beam cursor that + the original bug was referring to (run putty on a windows 7 vm) and + looks ok to me. + + Moving the core function to spice-util for testing. + +2013-10-18 Alon Levy + + cursor-channel.c: add cursor print function for debugging only (ifdefed) + +2013-10-16 Marc-André Lureau + + main: add missing vdagent caps name + This is useful in debug messages atm. + +2013-10-16 Christophe Fergeau + + sasl: Fix crash when ending a SASL session + When exiting remote-viewer after authenticating through SASL, I got + this crash: + + #0 0x0000000100a51870 in ?? () + #1 0x000000314d20c53e in _sasl_log (conn=, level=5, fmt=0x7fffe49893e8 "DIGEST-MD5 client mech dispose") + at common.c:1985 + #2 0x00007fffe4982d88 in digestmd5_client_mech_dispose (conn_context=0xaf1900, utils=0xaefd10) at digestmd5.c:4580 + #3 0x000000314d208654 in client_dispose (pconn=0xaf0710) at client.c:332 + #4 0x000000314d20b76b in sasl_dispose (pconn=0xa51898) at common.c:851 + #5 0x00007ffff7602dc7 in channel_reset (channel=0xa52250, migrating=0) at spice-channel.c:2493 + #6 0x00007ffff760f7b7 in spice_inputs_channel_reset (channel=0xa52250, migrating=0) at channel-inputs.c:615 + #7 0x00007ffff76030ac in spice_channel_reset (channel=0xa52250, migrating=0) at spice-channel.c:2551 + #8 0x00007ffff76031e0 in channel_disconnect (channel=0xa52250) at spice-channel.c:2570 + #9 0x00007ffff760283d in spice_channel_coroutine (data=0xa52250) at spice-channel.c:2368 + #10 0x00007ffff763d14b in coroutine_trampoline (cc=0xa51900) at coroutine_ucontext.c:58 + #11 0x00007ffff763ce30 in continuation_trampoline (i0=10819840, i1=0) at continuation.c:49 + #12 0x00000031342479c0 in ?? () from /lib64/libc.so.6 + #13 0x0000000000a51cc8 in ?? () + #14 0x0000000000000000 in ?? () + + It turns out that the sasl_callback_t data passed when calling + sasl_client_new() must be valid until sasl_dispose() is called. I could not + find mentions of this in the official documentation but + https://mail-archives.apache.org/mod_mbox/subversion-dev/201109.mbox/%3C20110908072256.GN25324@ted.stsp.name%3E + describes what happens. + Making the sasl_callback_t structure static should be enough to guarantee + that the data will stay around long enough. + + Display g_debug messages when SPICE_DEBUG is set + When SPICE_DEBUG is set but --spice-debug is not used, we fail + to set G_MESSAGES_DEBUG to the log domain used by spice-gtk, which + causes debug messages not to be printed as one would expect. + + Fix --spice-debug + If spice_util_set_debug() gets called before spice_util_get_debug(), + then the value set using spice_util_set_debug() will be overridden + by the result of g_getenv("SPICE_DEBUG") != NULL the first time + spice_util_get_debug() is called. + + This causes remote-viewer --spice-debug to not enable debug as + advertised if SPICE_DEBUG is not set. + + An alternate fix would have been to set debug_once.status to + G_ONCE_STATUS_READY but then we would lose the thread-safety + guarantees GOnce gives us. + +2013-10-10 Christophe Fergeau + + Fix switch to old SPICE protocol + After the previous commit, spice_channel_switch_protocol() is now + called when needed, but it's not doing anything. What happens is + that spice_channel_switch_protocol() triggers a channel disconnection + and then it queues an idle to reconnect (after having changed the + protocol version to be used). + + When spice_channel_recv_link_hdr() returns, we need to jump out of + the coroutine to let the idle trigger and the new channel coroutine + be started. But jumping out of the coroutine will call channel_disconnect() + which calls channel_reset() which disables the idle switch_protocol() + just queued. This causes the connection attempt to be apparently + stuck with nothing happening. + + Falling back to the older SPICE protocol is not the only situation + when we need to drop the current connection attempt and reconnect, + we also need to do that when the remote server returns + SPICE_LINK_ERR_NEED_SECURED to let the client know it needs to use + a secure port for this channel. This is handled by the 'switch_tls' + variable set in spice_channel_recv_link_msg and handled in + spice_channel_coroutine(). + + 'switch_tls' does the same thing as spice_channel_switch_protocol(), + except that it calls spice_channel_connect() after channel_disconnect() + has been called, which means the idle queued by channel_connect() + won't get cleared. + + This all that commit does, remove the spice_channel_switch_protocol() + method and use the same codepath as 'switch_tls' to handle the + reconnection. + + Reenable call to switch_protocol() on protocol version mismatches + This partially reverts b19acbc. This commit broke the fallback + to the old protocol as it added a check for c->peer_msg != NULL + before calling switch_protocol(), but mismatch between local + and remote protocol versions is detected before c->peer_msg is + allocated, so: + if (c->peer_msg != NULL && c->link_hdr.major_version != 1) { + SPICE_DEBUG("%s: error, switching to protocol 1 (spice 0.4)", + c->name); + spice_channel_switch_protocol(channel, 1); + return TRUE; + } + will never get triggered when c->peer_hdr.major_version != + c->link_hdr.major_version + + The crash described in b19acbc occurred when calling + spice_channel_recv_link_msg() in spice_channel_coroutine() + after a call to spice_channel_recv_link_hdr() failed and did + not set c->peer_msg. + + This commit removes the c>peer_msg check done before calling + spice_channel_switch_protocol() so that it gets called when needed, + but makes sure that we return FALSE to indicate that an error happened + and that we need to reconnect. This way we won't try to call + spice_channel_recv_link_msg() when c->peer_msg is NULL. + + Use latest warnings.m4 from gnulib + The one we were using does not work properly with clang, causing + the build process to try to use -f/-W options that are not + supported by clang. + +2013-10-10 Marc-André Lureau + + gtk-session: avoid mainloop recursion in clipboard_get + clipboard_get() exits when the clipboard data is received, or when the + agent connection state change. However, if the agent is already + disconnected, neither of those 2 conditions can be reached. + + Check if the agent is connected before running loop, exit early if not. + + gtk-session: fix clipboard_agent_connected + Use swapped connection to pass data as first argument to signal handler. + + main: fix notify of agent disconnection + spice_main_channel_reset_agent() reset connected state, and prevent + notify of property change. + + This is a minor regression introduced in c3adb24425. + +2013-10-03 Marc-André Lureau + + display: cache id is uint64_t + + display: fix palette regression + palette_get() used to return a ref, and palette_release() used to + release that ref. + + Since ed877341, the palette is no longer refcount'ed, since its usage is + exclusively local in common/canvas code. + + palette_release() shouldn't remove the palette from the cache. + + https://bugzilla.redhat.com/show_bug.cgi?id=1011936 + +2013-10-02 Alon Levy + + mono cursor: increase contrast, better looking putty cursor (rhbz 998529) + +2013-09-30 Hans de Goede + + spice-channel: Fix usbredir being broken since commit 159c6ebf + The usbredir channel uses spice_msg_in_raw to get its data, which uses + in->dpos to determine the msg size and that was no longer being set for + non sub-messages. + + https://bugs.freedesktop.org/show_bug.cgi?id=69935 + +2013-09-26 Marc-André Lureau + + win32: fix alt-tab grab regression + Since 5f67178c, alt-tab is no longer grabbed by the client. The keyboard + hook still needs to handle WM_SYSKEY{DOWN,UP} messages. + + https://bugzilla.redhat.com/show_bug.cgi?id=873341 + + build-sys: do not compile python binding with windows by default + + Update spice-common + + build-sys: add --with-audio=auto + Defaults to GStreamer on Windows, and PulseAudio otherwise atm. + + build-sys: fix --with-sasl + The default configure sasl auto setting will error out if SASL is + missing. Instead, silentely skip sasl configure if detected missing. + +2013-09-20 Marc-André Lureau + + build-sys: fix g_clear_pointer usage on old glib + As pointed out and verified on the ML after 0.21 release by Klaus + Hochlehnert. + +2013-09-18 Marc-André Lureau + + Release v0.21 + +2013-09-18 Colin Walters + + acl helper: Use ruid of invoker rather than looking up euid in /proc + This way we avoid a race condition if the parent execve()s a setuid + program (possibly this program). + + This is the same as the fix for pkexec which is CVE-2011-1485: + See: https://bugzilla.redhat.com/show_bug.cgi?id=692922 + +2013-09-18 Marc-André Lureau + + build-sys: fix bad cast on win64 + spice-widget.c:814:50: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] + g_return_if_fail(SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)d->win_mouse_speed, 0)); + +2013-09-13 Marc-André Lureau + + display: unshare the palette cache + As pointed out by Yonit on the ML: + > (1) the palette cache shouldn't be shared among the display channels. I.e., + > there should be one instance per channel, and not one instance in + > spice-session. + + channel: unref incoming migrate data + +2013-09-13 Marc-André Lureau + + gtk: simplify spice_channel_recv_msg + Use of coroutines allow to simplify spice_channel_recv_msg(), it doesn't + need to keep current reading state, it can rely on the coroutine stack + for that. + + gtk: use slices for frequently allocated objects + + gtk: use GHashTable in display_cache + The cache code isn't very quick, it shows up in profilers. Using + GHashTable allows to simplify the code while making it faster. + + channel: do not reenter the mainloop at every iteration + The current coroutine channel_iterate() creates a GSource for the socket + reenters the mainloop waiting for IO condition. This is really heavy + usage of mainloop showing up in system time and user space + profiling (10% of CPU time spent in mainloop overhead). Instead flush + all pending input messages before switching context and reentering main + loop. + + This is the kind of results I get with a replay: + + before: + + 2179,440455 task-clock # 0,629 CPUs utilized + 3 580 context-switches # 0,002 M/sec + 207 cpu-migrations # 0,095 K/sec + 48 909 page-faults # 0,022 M/sec + 7 362 442 301 cycles # 3,378 GHz + 5 256 957 520 stalled-cycles-frontend # 71,40% frontend cycles + idle + stalled-cycles-backend + 5 460 266 981 instructions # 0,74 insns per cycle + # 0,96 stalled cycles + per insn + 982 749 523 branches # 450,918 M/sec + 20 745 453 branch-misses # 2,11% of all branches + + 3,463422087 seconds time elapsed + + after: + + 1741,651383 task-clock # 0,522 CPUs utilized + 5 093 context-switches # 0,003 M/sec + 137 cpu-migrations # 0,079 K/sec + 49 033 page-faults # 0,028 M/sec + 5 874 567 974 cycles # 3,373 GHz + 4 247 059 288 stalled-cycles-frontend # 72,30% frontend cycles + idle + stalled-cycles-backend + 4 419 666 346 instructions # 0,75 insns per cycle + # 0,96 stalled cycles + per insn + 776 972 366 branches # 446,112 M/sec + 17 862 170 branch-misses # 2,30% of all branches + + 3,337472053 seconds time elapsed + + util: avoid calling getenv for every SPICE_DEBUG + That doesn't seem to really improve performance so much, + but that' s what we should do probably. + +2013-09-13 Marc-André Lureau + + display: keep a reference to the primary surface + Avoid hard-coding surface 0 as being primary, although in practice it + always is so far. Also a lot of lookups are primary, so add a shortcut + for this special case (~30% apparently), it shows some small lookup + speedup. + + before: + real 0m5.008s + user 0m3.253s + sys 0m2.015s + + after: + real 0m4.930s + user 0m3.133s + sys 0m2.027s + + display: make the hashtable to destroy the surface + Improve a bit the code by using hashtable ownership. + + display: replace ring with hashtable + With a Spice replay (a tool not yet merged, but available in dev + branches), the following commit improves a little bit performance by not + spending so much CPU time in looking up surfaces. I found initially + hotspot with "perf", and get a consistant ~200ms speedup with "time + spicy-stats" after replacing the ring. + + before: + real 0m5.147s + user 0m3.506s + sys 0m1.949s + + after: + real 0m5.008s + user 0m3.253s + sys 0m2.015s + + channel: add SPICE_DISABLE_CHANNELS + Allow to disable selectively channels, mainly used for testing, + ex: SPICE_DISABLE_CHANNELS=display spicy-stats -p 12345 + + channels: use spice_channel_set_handlers() + This allows to simplify a little bit derived class (no need to override + handle_msg), and allows the base class more flexibility (for example for + filtering messages, as in the following patch) + + channel: add spice_channel_set_handlers() + This function will allow to set base handlers and specific channel + handlers in a common way, instead of each channel having to override the + base channel virtual handle_msg(). + + display: use bitfields for surface flags + Checking by value make the flag fields useless. Unfortunately, when + adding more flags, the server will have to ensure it can safely send it, + by checking some of new client caps (for some features). + + Update spice-common + +2013-09-10 Dunrong Huang + + Fix _FORTIFY_SOURCE redefine error + If the _FORTIFY_SOURCE has been already defined, we shouldn't redefine + it, or it will raise a build error as below: + + In file included from spice-audio.c:36:0: + ../config.h:12:0: error: "_FORTIFY_SOURCE" redefined [-Werror] + spice-audio.c:1:0: note: this is the location of the previous definition + + Suggested-by: Christophe Fergeau + +2013-08-28 Marc-André Lureau + + Revert "tmp: debug MIGRATE_DATA" + This reverts commit f670e0197c37b2f12518f6d216642f67cdf5de84. + +2013-08-28 Alon Levy + + gtk/channel-cursor: copy spicec hack, RHBZ #998529 + flip -> unsupported by x11, since XCreatePixmapCursor has no invert + functionality, only a mask, shape, background and foreground colors. Use + this checkerboard hack to get some contrast for cursors in the guest + that relied on invert for the same contrast. + + gtk/channel-cursor.c: add cursor_type_to_string for debugging + + gtk/channel-display: only use SysV shm for x11 + + tmp: debug MIGRATE_DATA + +2013-08-28 Jonathon Jongsma + + Remove incorrect option context from spicy-stats + The argument given to g_option_context_new() was apparently copy/pasted from + spicy-screenshot and therefore inaccurate for spicy-stats. Since the actual + description of the program (from _set_summary()) is displayed on the next line + anyway, simply make the context NULL. + + channel-main: Fix minor documentation issue + Documentation for spice_main_clipboard_selection_request() refers to deprecated + signal 'main-clipboard' instead of 'main-clipboard-selection' + +2013-08-24 Marc-André Lureau + + tests: add some dos2unix tests + This is probably not exhaustive enough, but better than nothing. + + gtk: handle clipboard CRLF conversion + gtk+ internal text/utf8 is using LF conversion, on all platforms. + Even though the toolkit may only handle a single line ending type, we + may want to avoid the conversion for Spice use cases, gtk+ could learn a + new native utf8 target type, see also: + https://bugzilla.gnome.org/show_bug.cgi?id=706657 + + In the meantime, the only thing we need to convert, is to/from crlf + guest (from/to lf). This is what this change is about. + + It has been tested successfully with the various guest/client OS + combinations. + + util: add unix2dos and dos2unix + Convert line endings from/to LF/CRLF. + +2013-08-23 Marc-André Lureau + + Revert "channel-main: Convert text line-endings if necessary (rhbz#752350)" + This implementation assumes that the toolkit doesn't do any conversion + on its own. This is actually not the case, gtk+ converts line endings + already on windows. It would be pretty ugly to do conversions back and + forth at different levels. So the channel implementation shouldn't + try to do conversion, and implementation must be done at higher level, + where the actual system clipboard implementation is known (at + gtk-session for instance) + + Since this code hasn't been officially released, let's revert it and + implement a better crlf conversion handling in gtk-session in the + following commits. + + This reverts commit e45a446a9981ad4adaeff9c885962a8c6140333e. + + gtk: remove dead code + +2013-08-20 Uri Lublin + + win-usb-dev: ignore devices with addr 1 for LIBUSBX_API_VERSION + Starting libusbx version 1.0.13 (commit 8cd30bb7066f785ee78cf6c3dccafdbc4b957b50) + windows device enumeration changed and root hubs address number is 1 intead + of 0xff. + + This patch uses LIBUSBX_API_VERSION which was introduced after 1.0.13 release + (commit 9d368fc4774344d81ab02840f3a8478301bfb6fa). + + win usb: request for driver uninstall only for driver that were installed + Currently when spice_usb_device_manager_remove_dev() is called, + for windows clients a request to uninstall the driver is sent to usbclerk. + + This cause problems when 2 instances (A and B) of the client are running: + - Both A and B get notified about a new USB device when it's plugged in + - A is requested to usbredir the USB device. + - A requests usbclerk to install WinUSB driver for that device. + - usbclerk starts installing the driver + - Windows sends to both A and B - device removal events, which may cause + B to call spice_usb_device_manager_remove_dev. + - usbclerk completes installing the driver and reply to A + - B requests usbclerk to remove the WinUSB driver for that device. + + To prevent that, spice-gtk now requests usbclerk to remove the driver + only if it was the instance that requested the driver to be installed. + This is done with the help of a new device SPICE_USB_DEVICE_STATE_INSTALLED + state. + + rhbz#919166 + +2013-08-19 Christophe Fergeau + + Use g_slist_foreach_full glib implementation + For the compat case (glib < 2.28), we were using our own implementation + instead of directly reusing glib code. + +2013-08-19 Hans de Goede + + glib-compat: g_slist_free_full: pass the right ptr to destroy (rhbz#997893) + The destroy function passed to g_slist_free_full should be passed the elements + data pointer, not the element itself. + +2013-08-13 Christophe Fergeau + + Only use GOBJECT_INTROSPECTION_CHECK when available + Current el6 systems don't have gobject-introspection packages, + so the GOBJECT_INTROSPECTION_CHECK m4 macro is not available + on such systems. This makes it difficult to run autogen.sh + on these systems. + This commit uses m4_ifdef to check if this macro is available + before trying to use it, and makes sure introspection is + disabled when GOBJECT_INTROSPECTION_CHECK could not be found. + This allows to compile spice-gtk from git on el6 systems + with: + ./autogen.sh --with-gtk=2.0 --disable-gtk-doc --disable-vala + --disable-controller --disable-werror + +2013-08-06 Yonit Halperin + + usb-device-manager: fix compilation error when usbredir is disabled + +2013-08-06 Marc-André Lureau + + usb-widget: fix gtk2 Python bindings + The Python bindings generator failed to bind the USB widget, because of + the object/class declaration. The declaration was circumventing the + deprecated errors when compiling with GTK_DISABLE_DEPRECATED. We used + to need that because of broken gtk+ headers, but it is no longer + necessary since 15bd7ceba1434b5d710bfd16078044f30693467b. + +2013-07-22 Marc-André Lureau + + session: copy "ca" property in copy ctor + This fixes the GSpice-WARNING **: no cert loaded, when doing a seamless + migration (when using the "ca" property). + +2013-07-11 Christophe Fergeau + + smartcard: Only init manager once + The SpiceSmartcardManager is a singleton, so it does not make + a lot of sense to try to init it multiple times. This commit adds + a GOnce to ensure the manager is only init'ed once. + + smartcard: Handle VCARD_EMUL_INIT_ALREADY_INITED + When initializing a software smartcard, vcard_emul_init() can + report success, error, or indicate that initialization has already + been done. In this last case, we would assume that an error occurred + instead of behaving as if the initialization succeeded. + + vcard_emul_init() can end up being called multiple time if the + smartcard channel gets destroyed and recreated during the lifetime + of the application + + Fixes rhbz#815639 + +2013-07-08 Christophe Fergeau + + doc: Fix typo in code comment + + gst: Chain up dispose impl to parent class + + gi: Add (allow none) to optional const char * params + Without that annotation, it will not be possible to pass NULL to + these methods when using a gi-based binding. + + gi: Make sure usb-device-widget.c is introspected + If it's not, annotation we add to inline gtk-doc comments won't + be taken into account in the .gir file. + +2013-07-05 Hans de Goede + + usb-device-manager: Add support for libusb hotplug API + For now this makes the usb-code even more of a #ifdef party (albeit only + slightly so). But it does give us (theoretical, untested) usb support on + Mac OS X, and once the libusb Windows backend also gets hotplug support, we + can bump the required libusb version to a new enough one, and drop both the + windows gudev emulation as well as the gudev code-paths. + +2013-07-04 Hans de Goede + + usb-device-manager: Splitout device add / remove function + Split the device add / remove functions into a gudev specific part and + a generic part. This is a preparation patch for adding support libusb's + new hotplug API. + +2013-06-27 Hans de Goede + + Add spice_channel_string_to_type to map files + And document both spice_channel_string_to_type and + spice_channel_type_to_string. + + channel-main: Convert text line-endings if necessary (rhbz#752350) + This implements line-ending conversion following the specification in the + commit message of spice-protocol commit 7be0e88e7e03a956b364cc847aad11b96ed4 : + vd_agent: Add caps for the agent to signal the guest line-ending (rhbz#752350) + +2013-06-26 Marc-André Lureau + + Release v0.20 + + build-sys: bump spice-glib version + new symbols in spice-glib, bump before release + + doc: add missing symbols and versions + +2013-06-24 Yonit Halperin + + display: disabling adaptive video streaming via env var SPICE_DISABLE_ADAPTIVE_STREAMING + spice-server supports adaptive video streaming only if the client + publishes SPICE_DISPLAY_CAP_STREAM_REPORT. + + Disabling this feature is useful for debugging and performance comparison. + + display: video stats logging - improve readability and ease of parsing + +2013-06-24 Christophe Fergeau + + automake: Disable portability warnings + When they are enabled, autogen.sh fails with: + automake: warnings are treated as errors + gtk-doc.make:77: warning: GTK_DOC_V_SETUP_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:78: warning: GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:96: warning: GTK_DOC_V_SCAN_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:97: warning: GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:100: warning: GTK_DOC_V_INTROSPECT_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:101: warning: GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:132: warning: GTK_DOC_V_XML_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:133: warning: GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:149: warning: GTK_DOC_V_HTML_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:150: warning: GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:153: warning: GTK_DOC_V_XREF_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:154: warning: GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:185: warning: GTK_DOC_V_PDF_$(V: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + gtk-doc.make:186: warning: GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY: non-POSIX recursive variable expansion + doc/reference/Makefile.am:59: 'gtk-doc.make' included from here + autoreconf: automake failed with exit status: 1 + + on my F19. + -Wportability used to be automatically disabled with automake <= 1.12 when using + silent rules, but this is no longer the case with automake 1.13 which is what + fedora 19 uses: http://www.flameeyes.eu/autotools-mythbuster/automake/silent.html + "As of version 1.13, though, this opt-in is no longer necessary, as all the + Makefiles are generated to support them. The silent-rules option is now a + no-op, doing nothing at all, in particular not silencing the portability + warnings." + + This commit disables these warnings in order to avoid autogen.sh breakage + because of the use of -Werror, they can be reenabled once gtk-doc.make is + fixed to avoid these portability warnings. + + Remove obsolete files from POTFILES.in + intltool-update -M complains about them + + smartcard: Move down spice_smartcard_reader_is_software body + It's more consistent to have it close to + spice_smartcard_reader_insert_card() et al. + + Add spice_smartcard_manager_get_readers() + This returns the list of smartcard readers known to a given + SpiceSmartcardManager. This is useful to check whether a software + smartcard reader is available or not. + + smartcard: Add methods to act on software readers + Currently, the methods to insert/remove smartcards from a software + smartcard reader are global to the SpiceSmartcardManager singleton + rather than acting on a SpiceSmartcardreader object. + This commit adds insert/remove methods acting on such objects. + + smartcard: Report failure when software reader is missing + As there is no easy way to know if the SpiceSmartcardManager + has an associated software reader or not, it's better to report + failure instead of g_return_if_fail on attempts to use + spice_smartcard_manager_insert/remove_card with no software reader + available. + +2013-06-24 Hans de Goede + + Update spice-common + +2013-06-21 Marc-André Lureau + + proxy: remove trailing slash from proxy URL + Apparently, trailing slash are common for proxy URI. Is there a + specification for these kind of URI? + + (I cry that we don't have GUri yet to handle parsing... gbo#489862) + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=975472 + +2013-06-14 Marc-André Lureau + + win32: don't block key up events + The win32 ll keyboard hook avoid Windows and other application to + receive global keyboard events. But some key combinations can't be + filtered, such as Win+L. However, the windows lock screen doesn't catch + that the Win key is released, when virt-viewer still holds the hook and + filters it. + + So pressing Win+L quickly will lock the screen, but some key press in + the password entry will still be handled as if the Win key was pressed, + such as Win+P or Win+U and probably other, and prevents user from typing + his password. + + The only working solution I could find is to just let go all the release + key events in the hook. There doesn't seem any drawback with that. + + https://bugzilla.redhat.com/show_bug.cgi?id=917986 + + widget: release keys on grab-broken + This is similar to 8cbd5d745c221f788878c9c713f3b46a25828d3f and can be + reproduced by pressing Win+l while the widget has the keyboard + grab (pointer over the display). + + I have not reproduced implicit grab-broken event, I suppose they could + happen if the grab is stolen from within the app. In any case, it's + probably better to release the keys. + + This is related to: + https://bugzilla.redhat.com/show_bug.cgi?id=917986 + +2013-05-29 Hans de Goede + + Make sure our foo_get_type functions are thread-safe + While debugging: + https://bugzilla.redhat.com/show_bug.cgi?id=866718 + + I found a thread-safeness issue with a couple of foo_get_type functions + in polkit causing this crash. + + After this I decided to check if spice-gtk has the same issue, and it does, + since foo_get_type can be called from different threads, it is important to + make them thread-safe. + +2013-05-16 Marc-André Lureau + + widget: remove grab key filter + The widget currently filters out last key press from grab key sequence + if it's not a modifier key. But this will prevent nested usage of ungrab + combinations such as shift+f12. + + https://bugzilla.redhat.com/show_bug.cgi?id=889962 + + This will also make the following obsolete: + https://bugzilla.redhat.com/show_bug.cgi?id=846005 + + Build fix, use correct check version + +2013-05-15 Mattias Grönlund + + mingw: Fix non-working AltGr with some layouts + Running virt-viewer-x64-0.5.6.msi, on Windows 7, connecting to QEMU using + spice, AltGR key combinations fails (using Swedish keyboard layout both at + server and client). + + I suspect that this is a variant of + https://bugzilla.redhat.com/show_bug.cgi?id=904092. + + After some debugging, I realized that there is an extra VK_LCONTROL + keypress sent by Windows. This extra VK_LCONTROL will then make the key + e.g. AltGr-< actually be Control-AltGr-<, which is not interpreted as a | + sign. + + So in spice-widget.c : keyboard_hook_cb(), I added SPICE_DEBUG lines which + printed out the hooked->scanCode, and realized that this extra VK_LCONTROL + has a very suspect scanCode with bit 9 set. If I instead press the left + Ctrl key, it will also emit VK_LCONTROL, but with bit 9 cleared. + + So I just made sure that keyboard_hook_cb(), silently dropped these strange + VK_LCONTROL events, which seems to work for me. + +2013-05-15 Christophe Fergeau + + Fix printf format string warning + When doing a mingw32 build, I hit the following warning (which became an + error because of -Werror): + + channel-display.c: In function 'destroy_stream': + channel-display.c:1546:9: error: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type 'uint64_t' [-Werror=format=] + CHANNEL_DEBUG(channel, "%s: drops total duration %lu ==>", __FUNCTION__, drops_duration_total); + ^ + +2013-05-14 Marc-André Lureau + + Build fixes for gtk+2 + + Fix glib2 2.22 build after edf1daf5 + channel-display.c: In function 'display_update_stream_report': + channel-display.c:1273: warning: implicit declaration of function + 'g_get_monotonic_time' + +2013-05-13 Marc-André Lureau + + session: timeout after 10s of socket connect() attempt + https://bugzilla.redhat.com/show_bug.cgi?id=885101 + + Fix build after 577263aaf4c + +2013-05-13 Yonit Halperin + + channel-display: protect video streaming from temporarily unsynced mm_time (migration related) + rhbz#951664 + + When the src and dst servers have different mm-times, we can + hit a case when for a short period of time the session mm-time and + the video mm-time are not synced. If the video mm-time is much + bigger than the session mm-time, the next stream rendering will be + scheduled to (video-mm-time - session-mm-time), and even after + the different mm-times are synced, the video won't be rendered + till the rendering timeout that was scheduled based on a wrong mm-time, + takes place. + This patch protects from such cases. You can find more details in the + code comments. + + spice-session: new signal for notifying on a significant change in mm-time + mm-time can change after migration. This can cause video synchronization + problems after migration if not handled appropriately (see rhbz#951664). + + emit_main_context macro: handle calls from both coroutine context and main context + +2013-05-13 Marc-André Lureau + + vncdisplaykeymap: add wayland support + The Wayland keycode are just Linux evdev, but the Gdk backend + add the +8 offset used by Xorg evdev. + +2013-05-11 Marc-André Lureau + + vncdisplaykeymap: add broadway support + + keymaps: add basic x11 keysyms + Ok, this isn't a good idea, but atm, the browser don't seem to send + hardware keycode, and so Gtk+ broadway backend decided to use keysyms + representation, which spice-gtk receives as "hardware keycodes"... + + Since Gdk keysyms are same as X11, add a new x11 keysym to keymap. + + This is not going to fly,... + + vncdisplaykeymap: adapt gtk2 compat code + + vncdisplaykeymap: use a window to associate table + + widget: check backend is X11 + spice-gtk blindly assume the backend is X11 if it's compiled on + Unix. But nowadays, gtk+ support runtime backend selection. + + https://bugzilla.redhat.com/show_bug.cgi?id=961577 + + Remove unused spice_set_keyboard_lock_modifiers() + That code was used in early version to set client modifiers lock + but it is the wrong approach, and guest should follow client + state instead. + + Remove GnomeRR code + Changing client resolution is a bad idea, and never took up. + Remove some unmaintained experimental code. + + widget: release keys when the grab is taken elsewhere + gtk may propagate some press event up to the Spice display widget, but + a widget may take focus and grab the release event, so the guest will + keep seeing the key pressed. + + Releasing the keys when the grab is taken solves two menu-related bugs: + + https://bugzilla.redhat.com/show_bug.cgi?id=820829 + https://bugzilla.redhat.com/show_bug.cgi?id=924577 + + main: do not send monitors config if some are missing + Spice-gtk does a bit of client-side work by optionnally delaying sending + the monitor configuration to the guest automatically. However, the + client may be slow to set all the monitors, so teach the timer to not + fire the event unless at least the number of monitors set explicitely + enabled or disabled matches the number of display channels. + + This avoid some configuration races when connecting to a multi-channel + display server which is slow to set up. + +2013-04-30 Marc-André Lureau + + widget: don't grab mouse when switching to server mode + spice-gtk used to try taking the grab when switching to server mode, so + that the current mouse interaction (for example a drag), isn't + interrupted if the agent dies. However, shutting down a VM will + automatically try taking the grab when there is no tablet input, and + agent exits. + + Some users are complaining about it (especially when they don't know the + ungrab combination). + + Instead, let's try to keep the grab only if we have currently a mouse + button pressed. + + https://bugzilla.redhat.com/show_bug.cgi?id=873272 + +2013-04-26 Marc-André Lureau + + main: do not send monitor config if monitor state didn't change + Don't send monitor config after spice_main_set_display_enabled() if the + monitor state didn't change. + + This solves monitor "flashing", reconfiguring in a loop: + https://bugzilla.redhat.com/show_bug.cgi?id=952327 + +2013-04-24 Hans de Goede + + usb-redir-manager: Fix redirect_on_connect string mem leak + + usb-device-manager: Fix stray '\n'-s in g_warning calls + + usb-device-manager: Fix redirect_on_connect_rules mem-leak + + usb-device-manager: Add spice_usb_device_manager_get_devices_with_filter (fdo#63807) + + usb-device-manager: Error check spice_usb_device_manager_device_to_libdev calls + Under Windows all calls to spice_usb_device_manager_device_to_libdev may fail, + so error check them all. + + usb-device-manager: Avoid needless re-numeration of usb devs under Linux + libusb_get_device_list() is not exactly a cheap call (lots of sysfs and + usbfs accesses), so it is worth to avoid it where possible. + + This patch restores the old (pre win32 support addition) of dealing with + libusb-devices under Linux, it keeps the device from the first lookup + in spice_usb_device_manager_add_dev cached and uses that throughout. + + This also means that spice_usb_device_manager_device_to_libdev can no + longer fail under Linux, so no need to error check it. + +2013-04-23 Christophe Fergeau + + option: Allow multiple options in --disable-effects + Commit 82c367 added checks that the value passed to --disable-effects + is valid, but it does not take into account that it's perfectly valid + to pass multiple values separated by commas. This commit splits + the value passed to --disable-effects and checks each component separatey. + + Fixes rhbz#955277 + + Fix setting of SPICE_{GLIB,GTK}_REQUIRES + Because of a typo (REQUIRED vs REQUIRES), these variables only + contained the last require that was set rather than a concatenation + of all the needed libraries. + + Fix GNetworkAddress leak when opening spice session + +2013-04-22 Yonit Halperin + + channel-display: trigger re-sync of audio playback latency when there are frequent video frame drops + This was added in order to respond more quickly when the audio and video playback are + not synchronized, and when the latency between the client and the server + is high (i.e., when the server response to the status is delayed). + + playback: support syncing the playback latency via session + + spice-pulse: adjust the playback latency when the min-latency property changes + If the current latency is smaller than the new min-latency + value, we cork the playback till the target latency is achieved. + + Note: I didn't modify the prebuf configuration and used + pa_stream_prebuf, because pulse updated the prebuf only if + I set both prebuf and tlength to be target_latency*2. Then, + due to the tlength growth, each time the playback latency deviated + from the target latency, an underflow occurred. Since the latency + that is computed by the server is not exact and is based on its + current evaluation of the bit-rate, which is dynamic, it is better not + to change the tlength (in order to avoid unnecessary underflows). + + channel-playback: support SPICE_MSG_PLAYBACK_LATENCY + Add a new property for minimum playback latency. This property is + updated with the value from SPICE_MSG_PLAYBACK_LATENCY. + I also increased the default latency from 100ms to 200ms in order to + be more robust to different bandwidth settings. + The patch also updates spice-common submodule. + + channel-display: video stream quality report + Handle MSG_STREAM_ACTIVIATE_REPORT and send MSGC_STREAM_REPORT + periodically, or when the playback is out of sync. + The patch also updates spice-common submodule. + + channel-playback: provide access to playback properties via the session + Support checking whether an audio playback is active and what its latency + is. + + spice-pulse: update the playback latency automatically when it changes + + channel-display: collect and print video stream stats + also prints the number of underflows during a spice-pulse audio playback + +2013-04-12 Christophe Fergeau + + Revert "build-sys: keep common submodule up to date" + This reverts commit 5150285e1cba35570c29bd923df065d2c81f081e. + +2013-04-11 Marc-André Lureau + + session: enforce secure channels + + option: add --spice-secure-channels + + Add function to return Spice channel type from string + + Add function to return list of supported channels + + session: add secure-channels property + + channel: try TLS only once + A broken server may reply to switch to TLS again and again. spice-gtk + should only try once. + + cosmetic: fix indentation and comment + +2013-04-10 Marc-André Lureau + + Release v0.19 + + build-sys: bump spice-glib version + new symbols in spice-glib, bump before release + + Update README/TODO + + spicy-ss: quit when channel error + + Rename snappy to spicy-screenshot + Following discussion on the ML: + http://lists.freedesktop.org/archives/spice-devel/2013-April/012953.html + + build-sys: keep common submodule up to date + This requires git 1.8.2 to work properly. With this we should no longer + need to update the reference, assuming the tarball is always up to + date (that doesn't change from before, you need to update the submodule) + +2013-04-10 Alex Efros + + gnome-rr: keep user DPI + I'm running startx -dpi 144, but after exiting from spicy's full screen mode Xorg DPI reset to 96. Attached patch fix this issue by keeping user's DPI. + + See also: https://bugs.gentoo.org/show_bug.cgi?id=448362 + + https://bugs.freedesktop.org/show_bug.cgi?id=58715 + +2013-04-10 Tiziano Müller + + build: fix parallel install + This is a workaround for broken parallel install support in automake + with LTLIBRARIES, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328 + + Broken parallel install can be reproduced when building with --with-gtk=2.0 + and dies with: + /home/teuf/redhat/spice-gtk/gtk/.libs/libspice-client-gtk-2.0.so: file not recognized: File truncated + collect2: error: ld returned 1 exit status + libtool: install: error: relink `SpiceClientGtk.la' with the above command before installing it + make[5]: *** [install-pyexecLTLIBRARIES] Erreur 1 + m + +2013-04-10 Christophe Fergeau + + Use a GHashTable for list of file transfer tasks + This list is used to lookup tasks by their numerical id, so + a hash table is a more appropriate data structure for this kind of + uses. + +2013-04-10 Hans de Goede + + spice-common: Update + +2013-04-09 Marc-André Lureau + + widget: don't send current configuration back + spice-gtk keep the main channel monitor configuration in sync, but + shouldn't send back to the remote if disabled, as this may results in + different settings, for example if the remote has switched to + 16 bits. + + main: add spice_main_update_display() + Allow to change locally display resolution without sending it to remote, + this is useful to keep local information without bothering the remote. + +2013-04-09 Yonit Halperin + + channel_base: exit handle_migrate when expecting MIGRATE_DATA and receiving something else + Previously, when an error occurred on the src server side, and we + received other message than MIGRATE_DATA, this messages was forwarded + to the dest server, and made it crash. + +2013-04-09 Hans de Goede + + channel-main: Don't g_warn when not finding a file-xfer-id + Since the agent channel can have a significant latency, it is possible + for a cancel send from the client to the agent and a status message from + the agent to cross each other. If this happens then the file-xfer will no + longer be on the list. + + Printing a g_warning on this (rare but triggerable) condition will only get + us hard to debug bug reports, so turn it into a SPICE_DEBUG. + + channel-main: Cancel active file-xfers on channel/agent disconnect + + channel-main: Check no callbacks are pending on xfer start and end + We should never have pending callbacks when we receive a file-xfer start or + end (success) message from the agent. + + channel-main: Don't call g_input_stream_close on a NULL stream + If we fail to open a file, task->file_stream will be NULL, so we should + not call g_input_stream_close on it. + + channel-main: Allow calling file_xfer_close_cb with a NULL object + So that it can used for cleanup before we've a file_stream. + + Note this also gets rid of the weird double initialization of the local + stream variable. + + channel-main: Don't close the file_stream if callbacks are pending + If file_xfer_completed gets called while callbacks are pending we should + not call g_input_stream_close_async, because: + 1) Doing so while another operation is pending on the file_stream will fail + 2) Doing so while a non file_stream callback is pending may result in the + task being freed before the callback runs, resulting in a use after free. + + This patch fixes this by setting a pending flag when any callbacks are + scheduled, and clearing it when it runs + checking for task->error + from all callbacks and if that is set call file_xfer_completed again. + + channel-main: Use file_xfer_completed where appropriate + + channel-main: file_xfer_failed -> file_xfer_completed + Make file_xfer_failed usable for all file_stream closing. + + channel-main: Make SpiceFileXferTask-s ref the channel + So that the channel sticks around while their callbacks are completing. + + channel-main: Reset agent message receive state on agent stop + Discard any partially received messages from the agent on agent stop. + + channel-main: Add a spice_main_channel_reset_agent helper function + + channel-main: Drop bogus xfer_id check from file_xfer_send_start_msg_async + xfer_id > UINT32_MAX is never true since xfer_id is an uint32_t, and + thus explicit wrapping is not necessary since it will wrap every + UINT32_MAX + 1 itereations anyways. + + channel-main: Properly verify result in spice_main_file_copy_finish + Call g_simple_async_result_is_valid on the passed in result to verify it is + what we expect. + + channel-main: Call g_simple_async_result_is_valid first + Call g_simple_async_result_is_valid before using the result. + + Revert "channel-main: Fix dangling references to freed file-xfer-tasks on agent cancel" + The fix from commit 19313a133af0d2404b29914b5937219127ad455b is incomplete, + this commit added code to file_xfer_close_cb, to remove any reference to + the task being closed from the flushing queue. + + But file_xfer_flushed / file_xfer_flush_async execute file_xfer_data_flushed_cb + from an idle handler, so it is possible that when file_xfer_close_cb runs and + frees the task, it is not part of the flushing queue, but a + file_xfer_data_flushed_cb with the task as user_data argument still needs to + run, and when it will run it will refer to the now freed task. + + A related problem which is also addressed in this patchset happens when we + receive a file-xfer-cancel from the agent when an async operation on the + file_stream is pending, since we then cannot call g_input_stream_close_async + on it. This is fixed in the patchset by adding a pending flag to the task + struct, and the problem with pending flushes is solved in the same way. + + spice-widget: Fix file drag-n-drop mime-type + Currently the user can drag-drop text onto the widget, and it will try to + open it as a file, not good, this fixes this. + +2013-04-05 Marc-André Lureau + + cairo: fix reference leak + cairo_surface_finish() doesn't remove the reference, + cairo_surface_destroy() does and will call surface_finish(). + + Thanks to Uli Schlachter for noticing that in: + https://bugs.freedesktop.org/show_bug.cgi?id=61876 + +2013-04-04 Uri Lublin + + usb-device-manager: fix log messages to match vid:pid change + On Windows clients now USB devices are identified by their vid:pid + (sometimes these values are being held by variables "bus" and "addr") + Change log messages accordingly. + + usb-device-manager: Windows: identify devices by vid:pid instead of bus.address + rhbz#842816 + + Sometimes bus.address of a USB device changes upon WinUSB driver installation + for that device. This makes bus.address not a good identifier to use when + running on Windows machines. + + Instead this patch makes usb-device-manager, when running on a Windows client, + identify devices by their vid:pid. + + What changes were made in this patch (in addition to previous patches): + - vid:pid are asked from the udev. + - match functions that compare vid:pid were added + - when comparing devices vid:pid are used. + + This also means that a scenario where two USB devices with the same vid:pid + on a Windows client is not supported. However there was a problem with this + scenario before as on Windows drivers for (specific) USB devices are + installed based on their vid:pid. + + usb-device-manager: Windows: spice_usb_device_equal_libdev: compare vid:pid + When comparing spice_usb_device with a libusb_device on Windows clients, + use vid:pid instead of bus.address + + It seems that a device bus.address may change when WinUSB driver + is being installed. + + usb-device-manager: use a function to get vid:pid from a libusb_device + To be reused later. + + Also implemented a get_device_descriptor function (in case it will be + needed in the future). + + usb-device-manager: find_libdev: use a match function + Instead of comparing directly against . + + In preparation of comparing against vid:pid for Windows clients. + + usb-device-manager: find_device: use a match function + Instead of comparing directly against + + In preparation of comparing against vid:pid for Windows clients. + + usb-device-manager: constify spice_usb_device_get_ functions + + win-usb-dev: compare vid:pid instead of bus.addr (Windows) + It seems that sometimes, on Win7 clients, bus.addr is changing + when WinUSB driver is being installed (e.g. 4.1 -> 4.2). + + So compare vid:pid instead. + + win-usb-dev: make VID and PID available via get_property (Windows) + +2013-04-03 Hans de Goede + + channel-playback/record: Refuse audio-vol-msgs with 0 channels + Older servers send these, explicitly warn about this, rather then triggering + the following error later: + + (remote-viewer:8726): GSpice-WARNING **: set_sink_input_volume() failed: Invalid argument + +2013-04-02 Marc-André Lureau + + win32: do not handle win keys when the keyboard is not grabbed + Special-case on win32, filter out the win keys when not having the + keyboard grab. This is to avoid the win keys to be received both by + the guest and the client, which can be undesirable in general. + + https://bugzilla.redhat.com/show_bug.cgi?id=873341 + + Release pointer grab on grab-broken + On windows, the client receives a WM_KILLFOCUS event which generates + solely a keyboard grab-broken event. + + This event is received when pressing ctrl-alt-del (to show up the task + manager), and we need to release the pointer grab and clip region in + this case for the client to be usable. + + This also clear the clipping region when the client pops-up a dialog. + + Since keyboard focus is a pre-requisite for pointer grab, it sounds + logical to release the pointer grab if losing keyboard focus, but for + now, we just release it in grab-broken, as a result of discussion on + the ML. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=857114 + https://bugzilla.redhat.com/show_bug.cgi?id=922818 + +2013-03-29 Hans de Goede + + channel-main: Don't send empty monitor config on main_init with agent + Currently we send a monitor-config on any agent_start, including sending it if + the agent is already started when the main channel connects, but when the main + channel gets initialized, the display channels aren't intialized yet, so our + monitor config will be empty. Resulting in the Linux agent logging: + + spice-vdagent[1285]: err: client sent config with all monitors disabled + + This patch fixing this by only sending our monitor-config to the agent when + it (re)starts later on. + +2013-03-29 Marc-André Lureau + + main: copy the right nth monitor config + i is our counter for c->display[] + +2013-03-27 Christophe Fergeau + + Keep GSocketConnection around after initial connect + There has been reports of recent spice-gtk versions not working on + RHEL6 or Ubuntu 10.04. This happens because these systems have + an older glib version without: + + commit a0e1b226a21ca498b301981b0c89e89ad9a31eb1 + Author: Dan Winship + Date: Fri Apr 23 08:47:18 2010 -0400 + + GSocketConnection: don't close the socket if it's still reffed + + When disposing a GSocketConnection, don't explicitly close the + underlying GSocket. The GSocket will close itself if it gets + destroyed, and if it doesn't get destroyed, that presumably means the + app still wants to use it. Eg, this lets you use GSocketClient to + create a GSocketConnection, and then take the GSocket and destroy the + GSocketConnection. + + https://bugzilla.gnome.org/show_bug.cgi?id=616855 + + and spice-gtk commit 0f9a432c "session: allow to connect via HTTP CONNECT + proxy" changed spice_session_channel_open_host to get its socket by doing: + + open_host->socket = g_socket_connection_get_socket(connection); + g_object_ref(open_host->socket); + g_object_unref(connection); + (see socket_client_connect_ready) + + If glib does not have the commit mentioned above, then this won't + work as expected as open_host->socket will get closed when 'connection' + gets destroyed. + + This commit changes spice_session_channel_open_host to return a + GSocketConnection rather than a GSocket so that we can keep the + socket open even on older glib versions. + + Huge thanks go to Brad Campbell for doing all the + spice-gtk/glib bisecting work. + +2013-03-27 Marc-André Lureau + + Be less verbose about monitor config + +2013-03-25 Marc-André Lureau + + session: copy proxy setting + Solve migration falling back to switch-host method when using proxy + set through controller: + + https://bugzilla.redhat.com/show_bug.cgi?id=923894 + +2013-03-21 Marc-André Lureau + + gtk-session: remove clipboard timeout + A large clipboard may take longer than 7s on slow networks. Since the + Gtk+ API forces us to use an inner main-loop, exit it asap, if agent + is disconnected for instance. + + https://bugzilla.redhat.com/show_bug.cgi?id=752483 + + main: warn if receiving message from disconnected agent + + main: only notify on agent status change + +2013-03-19 Marc-André Lureau + + controller: don't try to set integrity on XP x64 edition + XP x64 uses version 5.2, but doesn't accept setting the pipe to low + integrity. + + 5.2 seems to be shared with many versions (server 2003 for example), + but only Vista+ matters, which is only major >=6. + + https://bugzilla.redhat.com/show_bug.cgi?id=918342 + +2013-03-15 Marc-André Lureau + + Notify of monitors when not using MonitorConfig + Windows guest don't use MonitorConfig, but we may want to notify the + client of the number of monitors. + + Related to: https://bugzilla.redhat.com/show_bug.cgi?id=919530 + + Update current resolution when agent is started + This ensures we have the requested resolution whenever possible. + +2013-03-15 Hans de Goede + + spice-widget: Reconfiguring the grab is only needed on win32 + Commit 8a7e72e3 "widget: regrab when widget is reconfigured" adds an + ungrab + grab call to the configure event handling code. Because: + "On Windows, we need to update the cursor clip. Call ungrab&grab to update it." + + But on X11 this is not needed, see man XGrabPointer, which explains that + the grab automatically adjusts to window resizing. + + Not only is it not needed it is also racy, causing spice-gtk based + apps to log messages like: + (remote-viewer:9935): GSpice-WARNING **: pointer grab failed 3 + + This patch fixes this by disabling the ungrab + re-grab on non-win32. + + spice-widget: Fix auto-grab on window size change + Commit 8a7e72e3 "widget: regrab when widget is reconfigured" adds an + ungrab + grab call to the configure event handling code. But it does this + without checking if the mouse is grabbed at all, causing an unsolicited + grab in certain scenarios, ie: + + 1) User boots a vm + 2) Connects with remote-viewer + 3) Goes and do some web-browsing while the vm boots + 4) Mouse happens to hover over the remote-viewer window + 5) Guests changes resolution (ie X starts) + 6) The mouse is grabbed, and when the user tries to move it to + click something in his web-browser this does not work. + + This patch fixes this by checking that the mouse is grabbed before doing + the ungrab + re-grab which is needed to reconfigure the grab to the new window + size / location. + + spice-widget: Ignore duplicate configure events + gtk seems to be sending us identical / repeated configure events quite + regularly (atleast under X11), we don't care about re-configures with the + same size + coordinates, so filter these out. + + Note this patch uses the SpiceDisplayPrivate mx and my members which + were already defined to store the window position, but not yet used. + +2013-03-11 Dunrong Huang + + spice-channel: Do not segfault fault if peer_msg was a NULL pointer + $ remote-viewer spice://192.168.0.233:111 # 111 is not a valid spice port + (remote-viewer:29381): GSpice-WARNING **: incomplete link header (-104/16) + Segmentation fault (core dumped) + + $ gdb /usr/bin/remote-viewer core + [Thread debugging using libthread_db enabled] + Using host libthread_db library "/lib64/libthread_db.so.1". + Core was generated by `remote-viewer spice://192.168.0.233:111'. + Program terminated with signal 11, Segmentation fault. + switch_tls=0x7f9eb6855b88) at spice-channel.c:1675 + + warning: Source file is more recent than executable. + 1675 switch (c->peer_msg->error) { + (gdb) bt + switch_tls=0x7f9eb6855b88) at spice-channel.c:1675 + at spice-channel.c:2299 + at coroutine_ucontext.c:58 + at continuation.c:49 + + c->peer_msg->error was accessed without checking the validity of pointer in + spice_channel_recv_link_msg(). Actually, c->peer_msg may be a NULL pointer if + we got a error in spice_channel_recv_link_hdr(). + + This patch fixes this error. + +2013-03-05 Christophe Fergeau + + usb: Remove device from ::devices before emitting device-removed + The code is currently removing the USB device that is gone from + the SpiceUsbDeviceManager::devices array after the device-removed + signal has been emitted. As signal handlers are called synchronously, + this means that the list returned by + spice_usb_device_manager_get_devices() will still contain the + removed device if it's called from the signal handler. + +2013-03-04 Hans de Goede + + channel-main: Handle the new VD_AGENT_FILE_XFER_STATUS_SUCCESS status msg + So that we can pass along an error from the agent to report an xfer error + after the last FILE_XFER_DATA message has been sent. + + Update spice-common + + channel-main: Send an error to the agent on file-xfer read error + So that the agent knows the rest of the file won't be coming. + + channel-main: Fix dangling references to freed file-xfer-tasks on agent cancel + While testing the agent error handling code I was triggering the + agent-file-xfer-cancel code-path in spice-gtk. This crashes due to the + flushing queue still having a reference to the task in question when its + gets cancelled from the agent side. This fixes this. + +2013-02-28 Christophe Fergeau + + Add fallback for g_key_file_set_uint64 + This was only added in glib 2.26 + + Don't try to call _wocky_http_proxy_get_type with old gio + Proxy support is only built when gio is newer than 2.26, don't try + to call symbols from wocky-http.c with older glib as this would + result in link failures. + +2013-02-26 Marc-André Lureau + + smartcard: do not register monitor before smartcard init + Never call vevent_get_next_vevent() before calling vcard_emul_init() + + Some mutexes are initialized in vevent_queue_init(), during emul_init() + + smartcard: trivial cleanup + + session: warn on invalid port value + +2013-02-20 Marc-André Lureau + + channel: swap tls status during seamless migration + In some cases, source and destinations may have different channel + encryption. We need to swap tls state too during seamless migration. + + https://bugzilla.redhat.com/show_bug.cgi?id=855870 + +2013-02-19 Marc-André Lureau + + main: use stable comparison function for monitors + If monitors are equal, compare them by their addresses, to get the + effect of a stable sort. + + main: use glib sort + Use glib sort for monitors. This allows to share the same + implementation and behaviour on various platforms. + +2013-02-13 Marc-André Lureau + + Release v0.18 + v0.18 + ===== + + - Build fix with Gtk+ unstable. + - MinGW build fixes with old headers + - Fixes rhbz#908057 + +2013-02-12 Hans de Goede + + usb-device-manager: Fix coldplug race + It is possible for us to see a device show up twice, if it gets plugged + in between us starting listening for new devices and doing "coldplug", then + it will get added once from the coldplug code, and then again from from + the hotplug code path. We already have code checking for this, but the check + is only compiled in under Windows -> Remove the #ifdef to also catch this + under Linux. + +2013-02-07 Marc-André Lureau + + display: keep monitor config updated if resize-guest is disabled + https://bugzilla.redhat.com/show_bug.cgi?id=908057 + + Update spice-common + +2013-02-06 Uri Lublin + + mingw: spice-widget: make sure MAPVK_VK_TO_VSC is defined + MAPVK_VK_TO_VSC is defined in the file: + /mingw/include/winuser.h + + In older mingw-headers the definition of MAPVK_VK_TO_VSC is + defined only -- #if _WIN32_WINNT >= 0x0601 + +2013-02-06 Marc-André Lureau + + build-sys: don't use -Wstrict-prototypes with Gtk+ 2.0 + + build-sys: remove GTK_DISABLE_DEPRECATED + Gtk 3.0 no longer includes deprecated headers if it's defined: + http://git.gnome.org/browse/gtk+/commit/?id=a1de67f438f057711353a55b322babce7044226f + + We added it as a workaround for Gtk 2.0 build issue. + + build-sys: bump spice-glib version-info + spice-glib version-info should have been bumped, since we have new + symbols. + + 249dd73132a7ecc1ceb32b4fea6529491ca219d3 + + Release v0.17 + v0.17 + ===== + + - Update spice-common with fedora 875348, 826036 fixes + - Multi-monitor fixes (avoid monitor order shuffling, fix mouse offset + if monitor 0 is not at +0+0 and let agent do monitor offset) + - Add support for VD_AGENT_CAP_SPARSE_MONITORS_CONFIG + - Add controller & session "proxy" properties + - Add drag and drop file copy support to send file to guest, you will + need capable agent to use that feature. Adds spice_main_file_copy_async() + - Introspection fixes + - Build fixes + + spice-proxy: explicitely mark as internal + +2013-02-06 Hans de Goede + + widget: Fix mouse position reporting for multiple monitors on 1 display channel + VDAgentMouseState contains a display_id and expects coordinates in multi-mon + mode to be relative to the origin of the monitor specified by the display_id. + + The agent will then adjust the mouse coordinates for the position of the + monitor as configured in the guest. + + In multiple monitors on 1 display channel spice-gtk is wrongly setting + display_id to the channel_id (which is 0 for all monitors), and is working + around the problems this causes by doing the adjustment of the mouse position + itself. + + But the agent is still applying the correction for the monitor position to + all VDAgentMouseState messages it gets, and since for all monitors a display_id + of 0 is reported it always uses the position of display 0 for the correction. + + Since the position of display 0 is usally +0+0 this usually works, but as soon + as the position of display 0 is not +0+0, the correction will get done twice + for display 0, and the display 0 position will wrongly get added the mouse + position for other displays. + + This patch fixes this by properly setting display_id, and removing the + modification of the mouse coordinates as that is already done in the agent. + +2013-02-04 Natanael Copa + + build: fix for automake-1.13 + Use AC_CONFIG_HEADER instead of deprecated AM_CONFIG_HEADER. + +2013-01-31 Yonit Halperin + + update spice-common submodule + obtaining a fix related to palettes caching (fedora 875348, 826036) + +2013-01-30 Marc-André Lureau + + controller: add proxy property + +2013-01-29 Marc-André Lureau + + session: clear SpiceSession:proxy also if SPICE_PROXY is NULL + + Add SpiceSession:proxy + Add a session property to set proxy setting, since it is racy to rely + on setenv(). Also doing so would override system environment, which + will modify other session too sharing the same process. + +2013-01-28 Marc-André Lureau + + proxy: initialize proxy at session construct time + + Fix a bunch of gtkdoc/giscan warnings + + Update spice-common + + session: simplify a little bit open_host_idle_cb + open_host->error is only set if we try to use a proxy. Let´s make that + more clear. + +2013-01-21 Marc-André Lureau + + build-sys: generate THANKS at dist time + +2013-01-21 Jasper Lievisse Adriaanse + + build-sys: Use a portable variable assignment in configure.ac + + build-sys: missing sys/types.h in gtk/channel-display.c + +2013-01-18 Hans de Goede + + channel-main: Fix monitors_align to not shuffle monitor order + Before this patch monitor_align was calling qsort directly on the + VDAgentMonConfig monitors array, but VDAgentMonConfig does not contain + an id, so the order matters! + + This fixes (for example) 2 issues with having 3 windows/monitors on a row + numbered 1-3, ordered left-to-right as 1-2-3, and then changing the + ordering to 1-3-2: + 1) Window 3 would be resized to the size of window 2, and window 2 would + get resized to the size of window 3. + 2) Dragging a window on monitor 1 over its right edge, makes the part over + the edge show up on the right monitor, rather then on the middle. + This is happening because the agent is configuring qxl-1 (which is monitor 2) + with the monitors[1] data, which after the qsort contains the size and + coordinates of monitor 3. + + Note this only happens with virt-viewer fixed to properly send window + coordinates, as before that all monitors had x and y set to 0 making the + sort a nop. + + channel-main: Add support for VD_AGENT_CAP_SPARSE_MONITORS_CONFIG (rhbz#881072) + + spice-widget: update_monitor_area: Fix memory-leak on whole fallback + When we've successfully gotten the monitors display-channel property, but + still end up falling back to whole-display mode, we still need to free + the monitors array. + + spice-widget: Search monitor info by display monitor-id + As discussed indexing the display-channel's monitors property by monitor-id + causes problems with the vdagent's new sparse monitor config support. + + Searching the monitors property by monitor-id avoids these problems. + +2013-01-16 Andrew Hughes + + build-sys: fix out-of-tree build with vala + +2013-01-16 Cole Robinson + + Fix introspection for send_keys + Without this I can't find a usable way to call this API with the + introspected python bindings. + + https://bugs.freedesktop.org/show_bug.cgi?id=59444 + +2013-01-14 Marc-André Lureau + + gtk: avoid use gtk+ 3.0 only API + +2013-01-12 Marc-André Lureau + + file-xfer: always take error if set in xfer_read_cb() + + file-xfer: use file_xfer_..() prefix for all internal copy functions + + file-xfer: move file_close_cb() above all to ease reading + + file-xfer: try to report any error from file_info_async_cb() + + file-xfer: non-programming errors should be reported in async + It is fine to not return async errors for programming errors via + g_return_if_fail() and friends, however, we need to return proper + error if it's a normal run-time error. + + file-xfer: avoid g_alloca() usage when possible + +2013-01-12 Dunrong Huang + + file-xfer: handle "drag-data-received" signal + When user drags a file to SpiceDisplay and drops it, a signal named + "drag-data-received" will be emitted, the signal will be received by + SpiceDisplay, then our signal handler should receive data which contains + file path, and call spice_main_file_copy_async() to transfer file to guest. + + file-xfer: disable file-xfer when agent is not connected + + file-xfer: handling various transfer messages in main channel + This patch is aimed to handle various file xfer messages. + + How it works: + 0) our main channel introduces a API spice_main_file_copy_async(). + + 1) When user drags a file and drop to spice client, spice client will + catch a signal "drag-data-received", then it should call + spice_main_file_copy_async() for transfering file to guest. + + 2) In main channel: when spice_main_file_copy_async() get called with file + list passed, the API will send a start message which includes file + and other needed information for each file. Then it will create a + new xfer task and insert task list for each file, and return to caller. + + 3) According to the response message sent from guest, our main channel + decides whether send more data, or cancel this xfer task. + + 4) When file transfer has finished, file xfer task will be removed from + task list. + +2013-01-11 Marc-André Lureau + + Release v0.16 + v0.16 + ===== + + - Fix crash with SSL connection (#890464) + - Send monitor config to the agent on spice_main_set_display_enabled() (#881072) + - Fix channel leak and wrong condition in spice_channel_flush() + - Build fixes + + spice-channel: fix state condition check in flush() + + spice-channel: plug a channel ref leak + +2013-01-09 Hans de Goede + + Send monitor config to the agent on spice_main_set_display_enabled (#881072) + Currently we send an updated monitor-config to the agent whenever some + of the display settings are changed (whenever spice_main_set_display is + called), including when a new display is enabled, as that involves + creating a new window, which calls spice_main_set_display. The only + exception to this is when a display gets disabled. + + This is rather inconistent, it causes the user to be able to move windows + in the guest to the now no longer visible monitor, and any windows which + were already there are hidden... until something else triggers us sending + updated monitor info. Withe gnome3 an alt-tab away and back again from a still + open display-window is enough to trigger the update, and then the guest will + all of a sudden become aware of the monitor no longer being there and + re-arrange windows accordingly, on an alt-tab in the client machine ... + not pretty. + + So lets make things consistent and also send the agent updated monitor info + from spice_main_set_display_enabled, like we already do from + spice_main_set_display. + +2012-12-27 Marc-André Lureau + + Fix switching to TLS regression + The commit fcbbc248a8f885f9a9a6e7c47d7aae0c1ab3cd1b changed the way a + channel coroutine is exiting. In particular, it was going through the + coroutine main cleanup (finishing in main coroutine) while switching + to TLS is recycling the channel. That part of the code is a bit + difficult to grasp, but with this refactoring, I think it makes it + easier to understand the reconnection. + + Clean-up idle handler when leaving the open_host_idle() + An explicit yield back to the channel coroutine when the idle function + is still pending will leave it in the background, referencing objects + that may no longer exist. Make sure we remove it when + channel_open_host() is resumed. + +2012-12-21 Christophe Fergeau + + mingw: Fix link errors + Without this patch build fails with: + + CCLD libspice-client-glib-2.0.la + .libs/spice-channel.o: In function `spice_channel_coroutine': + /home/teuf/redhat/spice-gtk/gtk/spice-channel.c:2287: undefined reference to `_imp__setsockopt@20' + .libs/channel-display.o: In function `create_compatible_dc': + /home/teuf/redhat/spice-gtk/gtk/channel-display.c:672: undefined reference to `_imp__CreateCompatibleDC@4' + ../spice-common/common/.libs/libspice-common.a(canvas_utils.o): In function `release_data': + /home/teuf/redhat/spice-gtk/spice-common/common/canvas_utils.c:41: undefined reference to `_imp__DeleteObject@4' + ../spice-common/common/.libs/libspice-common.a(canvas_utils.o): In function `surface_create': + /home/teuf/redhat/spice-gtk/spice-common/common/canvas_utils.c:192: undefined reference to `_imp__CreateDIBSection@24' + /home/teuf/redhat/spice-gtk/spice-common/common/canvas_utils.c:208: undefined reference to `_imp__DeleteObject@4' + ../spice-common/common/.libs/libspice-common.a(ssl_verify.o): In function `inet_aton': + /home/teuf/redhat/spice-gtk/spice-common/common/ssl_verify.c:38: undefined reference to `_imp__inet_addr@4' + ../spice-common/common/.libs/libspice-common.a(ssl_verify.o): In function `verify_hostname': + /home/teuf/redhat/spice-gtk/spice-common/common/ssl_verify.c:216: undefined reference to `_imp__inet_ntoa@4' + collect2: error: ld returned 1 exit status + +2012-12-21 Marc-André Lureau + + Release v0.15 + v0.15 + ===== + + - Add HTTP Proxy support (only with glib >= 2.26) + - Add "port" channel support, to allow arbitrary communication on top + of spice connection + - usb-redir: fix migration support + - win32: various keyboard & mouse fixes + - Add info message when USB dialog is empty + - Fix initial black screen on some 16bits guest + - Various bug fixes and improvements + + build-sys: update sym-files + + session: improve open_host() clean-up + Make sure the GSocketClient is unref when leaving the function, and + not left around in some unfinished async state. + + session: do not unref() NULL connection + #3 0x00007ffff59cfb3b in g_object_unref (_object=0x0) at gobject.c:2916 + #4 0x00007ffff6ea9c20 in socket_client_connect_ready (source_object=0x87ced0, + result=0x8a58f0, data=0x7fffe3fffa80) at spice-session.c:1606 + #5 0x00007ffff5ea1278 in g_task_return_now (task=0x8a58f0) at gtask.c:1102 + +2012-12-20 Hans de Goede + + acl-helper policykit policy: Allow redir by default for console users + This makes usb-redir a lot more userfriendly to use. This has been + discussed with the security team and they are ok with it, rationale: + + Since we only set to yes, we only give raw usb access + to users *physically present behind the machine*. This is ok since + they already have full control over usb devices anyways, they can + always just unplug the device and put it in a user controlled machine. + + This follows how we already grant a great deal of access to users + *physically present behind the machine* including dangerous things like + /dev/sg access for cd/dvd writers. And raw usb access to all devices which + happen to have a userspace driver rather then an in kernel driver. + + Also the opening up is limited compared to the existing opening up of + other devices listed above in that: + + 1) It will only happen on machines which have spice-glib installed + 2) We are not opening up the device nodes rights automatically, as an udev rule + would do. So there is no chance that any random app can start (accidentally) + poking the devices. + +2012-12-19 Hans de Goede + + spicy: Fix compilation breaking due to a compiler warning + This fixes: + spicy.c:1711:10: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result] + +2012-12-17 Marc-André Lureau + + controller: fix new vala warnings + send_msg() is done in background, use .begin + + controller.vala:62.3-62.10: warning: implicit .begin is deprecated + foreign-menu.vala:44.3-44.10: warning: implicit .begin is deprecated + foreign-menu.vala:59.3-59.10: warning: implicit .begin is deprecated + foreign-menu.vala:70.3-70.10: warning: implicit .begin is deprecated + Compilation succeeded - 4 warning(s) + + channel: switch to protocol 1 on error during link-time + The Spice server doesn't wait until all the data are received by the + remote before closing the socket (that would need SO_LINGER?). Under + some racy conditions, the client may not have received the link reply + indicating the server protocol version mismatch, which would trigger + reconnection with compatible protocol. + + It seems to happen on local networks with Windows sockets (error + WSAECONNRESET). To workaround that issue, spice-gtk can try to + reconnect with protocol 1 when a socket error is encoutered during + link-time. + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=874698 + +2012-12-14 Marc-André Lureau + + session: allow to connect via HTTP CONNECT proxy + Allow to connect to a Spice server via a HTTP proxy with CONNECT + method. spice-gtk will use the SPICE_PROXY environment variable, which + can currently only have the following syntax: [http://]hostname[:port] + + This is paving the way to more proxies support (socks4/socks5). + + This code is now entirely sync (it was not even completely async), the + following patch will make it all async again. + + Tested with Squid, locally only. + + Add SpiceProxy object + Add a simple object to handle the SPICE_PROXY values. + + It's not clear to me whether each GIO user needs to handle the proxy + configuration, or if there is a more global mechanism (via + g_network_address_parse_uri()) + + Also, the parsing is currently very limited and only support basic + HTTP proxy URI. In the future, we really want to rely on GUri or + similar instead... + + Add wocky HTTP proxy + Courtesy of Nicolas Dufresne + + It might make sense to include this proxy in glib/gio, but it is still + missing some features according to its author, namely SSL and perhaps + better CRLF. + + spice-channel: remove unnecessary g_socket_close() + + spice-channel: plug a small memory leak + +2012-12-10 Uri Lublin + + gtk/channel-port: include glib-compat for g_clear_pointer + + glib-compat: add g_slist_free_full + + channel-display: add more protection against bad access to streams + +2012-12-07 Dunrong Huang + + spice-widget: Fix rendering issue with X11 backend enabled + commit 5ec6e4d fixes a rendering issue on win32 platform, but raises another + bug on linux platform. + + If X11 backend is enabled, app window will becomes while screen when draging it. + This bug can be reproduced easily: + compile spice-gtk using: + $ ./configure --with-gtk=2.0 --with-x11 + $ make + $ gtk/spicy -h host -p port + +2012-12-05 Marc-André Lureau + + channel: rely on couroutine instead of channel state + We can simplify the channel state callback and simplify a little + the code by relying on coroutine state instead. + + spicy: demo SpicePort usage + spicy has been modified to recognized 2 different port types to play + with: + + * org.spice.spicy: will connect the port to the current stdin/stdout, + and can be used as a chardev for the qemu monitor + + * org.spice.spicy.break: will send a break event on connect and + disconnect immediately (exercice the port event and flush) + + Add a port channel + A Spice port channel carry arbitrary data between the Spice client and + the Spice server. It may be used to provide additional services on top + of a Spice connection. For example, a channel can be associated with + the qemu monitor for the client to interact with it, just like any + qemu chardev. Or it may be used with various protocols, such as the + Spice Controller. + + A port kind is identified simply by a fqdn, such as org.qemu.monitor, + org.spice.spicy.test or org.ovirt.controller... + + channel: add flush_async() + Add spice_channel_flush_async() that asynchronously will write all the + pending channel data. + + update spice-common + +2012-11-30 Marc-André Lureau + + channel: make spice_msg_out_send() slightly easier to read + Avoid the obfuscating many -> indirection by using the + SpiceChannelPrivate *c variable. + +2012-11-27 Marc-André Lureau + + win32: fix rendering issue when widget is partially off screen + Gtk+ in win32 has a rendering bug with window non-buffered: + https://bugzilla.gnome.org/show_bug.cgi?id=688962 + + According to Alex Larsson, this shouldn't affect performance much, + since there is already extra-copy done for offscreen buffers, and + might even make it faster in gtk+ 3.0... + + Fixes: + https://bugzilla.redhat.com/show_bug.cgi?id=874482 + +2012-11-22 Marc-André Lureau + + channel: learn to load certificate from memory + Sadly, OpenSSL doesn't provide a way to load certificate from memory, + but all the functions necessary to do so are actually public, so we + can implement our own version and avoid files, how awesome! + + Add SpiceSession:ca property + +2012-11-19 Marc-André Lureau + + win32: translate virtual-key code to scancode via MapVirtualKey + Local client keyboard layout shouldn't affect hardware scancode sent + to guest, so that guest keyboard layout configuration can map it + properly. + + Unfortunately, the Win32 GdkEventKey.hardware_keycode isn't a hardware + scancode, but the Windows virtual-key code. We could modify Gdk to + return the scancode (available in MSG.lParam or via global hook), but + that would mean some Gdk breakage, or some unnecessary complexity. + Instead, we can rely on MapVirtualKey(), which translates the + vitual-key code into a scan code using current keyboard layout. + + This solves the following bug: + https://bugzilla.redhat.com/show_bug.cgi?id=871125 + +2012-11-18 Marc-André Lureau + + win32: track current window handle + We need current window handle for the global keyboard hook. It is not + enough to rely on focus-in event to set it, so do it also in + key-event. This avoids extra warnings on Windows. + +2012-11-14 Marc-André Lureau + + win32: clip and move cursor within window region + Windows grab do not exist like on X11, so we need to clip the cursor + to our client window, while making sure it doesn't overlap with + windows statusbar. When wrapping the cursor, we need to make sure we + also stay within the clip region, or else the clip is inverted + (pointer can't enter the clip region anymore), and we also lose the + keyboard hook/grab. + + The end result works better than spicec, which didn't exclude the + Windows statusbar, and was subject to losing pointer when wrapping + mouse over it. + + Another approach I have been playing with is to clip the cursor, and + process raw input messages, this will have the advantage to work even + when the client is completely out of the working area (under the + statusbar for example), but the complexity involved is too high for + very poor benefit (interacting with a non-visible client), we could + even argue that the behaviour implemented by this patch is more + correct (it refuses to grab the cursor if the client isn't visible in + the working area). + + v2: + - choose the nearest monitor for clipping + - the ClipRegion is in Windows coordinate, we can't use gdk warp + - fix https://bugzilla.redhat.com/show_bug.cgi?id=872640 + + This solves the following bugs: + https://bugzilla.redhat.com/show_bug.cgi?id=857430 + https://bugzilla.redhat.com/show_bug.cgi?id=857389 + +2012-11-12 Marc-André Lureau + + widget: regrab when widget is reconfigured + On Windows, we need to update the cursor clip. Call ungrab&grab to update it. + + widget: don't redraw server mouse until moved + When switching between client mode and server mode, the pointer is + being invalidated on each display and the cursor will end up being + drawn on both. Since there is no information on which display the + cursor is supposed to be until a move is received, hide the cursor + until it actually moves. + +2012-10-25 Uri Lublin + + win-usb-driver: use usbclerk new message: USB_CLERK_DRIVER_SESSION_INSTALL + With this message usbclerk keeps a list of devices for which + a libusb driver was installed (per connection). + When a spice-gtk client exits, the connection is closed, and + usbclerk uninstalls the driver for all devices in the list. + + That means we need to keep the connection open, so added + the win-usb driver installer to usb-device-manager's priv. + + This prevents the case were the user exits the client, while a usb + device is connected to the guest, and can not use the device from + the client machine. + + rhbz#869542 + +2012-10-25 Marc-André Lureau + + controller/win32: limit access to current user only + Based on RHEV spicec-win only code. + + controller/win32: allow ActiveX connection on untrusted website + Set low integrity on named-pipes. + + This bug was originally resolved as: + https://bugzilla.redhat.com/show_bug.cgi?id=668980 + + Fixes regression: + https://bugzilla.redhat.com/show_bug.cgi?id=844461 + +2012-10-24 Uri Lublin + + spice-gtk: controller: log messages received from a controller + +2012-10-23 Marc-André Lureau + + win32: implement disabling mouse accel + https://bugzilla.redhat.com/show_bug.cgi?id=867885 + + move mouse acceleration code in a seperate function + + Fix disabling mouse acceleration on X11 + It turns out the acceleration code didn't work, because we didn't set + it to the default values. Then we need to restore it back. Eventually, + it would be nicer to inhibit gnome-settings-daemon to apply devices + changes, and restore settings when un-inhibiting. + + https://bugzilla.redhat.com/show_bug.cgi?id=867885 + +2012-10-19 Marc-André Lureau + + Empty host subject from qemu should only validate hostname + Validate empty host subject from qemu exactly like when no explicit + host subject is specified. + + https://bugzilla.redhat.com/show_bug.cgi?id=858228 + + channel: improve debugging message + The open_host() can return FALSE when the connection is discarded or + skipped. Improve the message to not indicate a failure. + + https://bugzilla.redhat.com/show_bug.cgi?id=858232 + + Print list of supported channels + https://bugzilla.redhat.com/show_bug.cgi?id=834513 + +2012-10-18 Hans de Goede + + channel-inputs: Fix sending 00 scancodes to guests with scancode cap + The code for handling single key up / down events in spice-server is: + SpiceMsgcKeyDown *key_down = (SpiceMsgcKeyDown *)buf; + uint8_t *now = (uint8_t *)&key_down->code; + uint8_t *end = now + sizeof(key_down->code); + for (; now < end && *now; now++) { + kbd_push_scan(keyboard, *now); + } + + Notice the *now, which makes sure that no scancodes with the value 0 get + send! But the new SPICE_MSGC_INPUTS_KEY_SCANCODE in the server does: + + uint8_t *code = (uint8_t *)buf; + for (i = 0; i < size; i++) { + kbd_push_scan(keyboard, code[i]); + } + + And thus will push any 0 bytes in the buffer. Resulting in these message + in the guest: + + atkbd serio0: Unknown key pressed (translated set 2, code 0x0 on isa0060/serio0). + atkbd serio0: Use 'setkeycodes 00 ' to make it known. + + Rather then making the server skip 0 bytes I believe it is better to just + make spice-gtk not send these in the first place, which is what this patch + does. + +2012-10-17 Marc-André Lureau + + win32: implement sync_keyboard_lock_modifiers() + Fix numlock numerical keypad being broken: + https://bugzilla.redhat.com/show_bug.cgi?id=856538 + + spicy: show the correct ungrab key combination + The gtk accelerator for ungrab is useless, since it has to be handled + by the spice widget only. It could be useful to still show the ungrab + key sequence in the menu (for help), but unfortunately, spice-gtk grab + sequence syntax is not the same as gtk accelerator syntax, and that + would be needlessly complicated to handle. + + Also correctly show the configured sequence in the status bar when the + widget has the grab. + + https://bugzilla.redhat.com/show_bug.cgi?id=851090 + +2012-10-16 Marc-André Lureau + + widget: apply color conversion when creating image + The color conversion only happened during "invalidate", but we also + need to apply it when the image is created in the first place. + + This solves initial screen being black after connection to agent-less + guest with 16b colour depth: + + https://bugzilla.redhat.com/show_bug.cgi?id=843134 + +2012-10-15 Marc-André Lureau + + win32: ignore hardware keycode 255 + It's a reserved value, and it doesn't have a valid scancode + translation. Currently, We hit a warning in the delayed key handling + later. + + vnc keymap: fix incorrect table size + This lead to out of bound array access + + Add a warning if scancode lookup failed + This helps tracking some send_keys() issues, such as + https://bugzilla.gnome.org/show_bug.cgi?id=686170 + + win32: fix quote key handling + Fix keymaps to correctly handle the quote key. + + https://bugzilla.redhat.com/show_bug.cgi?id=856317 + +2012-10-11 Hans de Goede + + Add spice-usbredir-filter alias for spice-usbredir-auto-redirect-filter (v2) + For commandline backward compatibility with older spice-gtk versions. + + Changes in v2: + -warn about spice-usbredir-filter being deprecated when it gets used + + UsbDeviceManager: Don't warn on EINTR + + UsbDeviceManager: Hookup redirect-on-connect property + + UsbDeviceManager: Build channel list after building the device list + This is necessary for redirect-on-connect + + UsbDeviceManager: Add a redirect-on-connect property + + Rename spice-usbredir-filter option to spice-usbredir-auto-redirect-filter + The spice-usbredir-filter cmdline option was not chosen well, as it does + not indicate what it filters. Now that we are also getting a filter for + selecting already plugged in devices to redirect when a spice connection gets + established, it needs to be renamed to make its function more clear. + +2012-10-09 Hans de Goede + + usb-redir: Fix read error handling depending on SpiceUsbDevice == libusb_device + This has not been true for a while now, but since getting an error return + from usbredirhost_read_guest_data() is rare no one has tripped over this + sofar. + +2012-10-08 Hans de Goede + + channel-usbredir: Properly reset state from reset callback + This is necessary to be able to use the usbredir channel after a + non seamless migration. + + Set channel state before calling channel_reset + This way functions called from the channel_reset function can rely + on state accurately reflecting the state. This is necessary to stop + channel-usbredir's reset callback from trying to send the initial + hello message while the channel is no longer in a connected state. + +2012-10-03 Christophe Fergeau + + Update spice-glib-sym-file for new symbol + +2012-10-01 Christophe Fergeau + + usb: Add info message when USB dialog is empty + From rh bug #804187: + « The redirection dialog can feel a bit strange when there is no device to + redirect. + + It could be useful to provide a help message indicating that there is no + device to redirect yet, and that the user can insert a USB device to + redirect, and some related guidance. » + + This commit adds a "No USB devices detected" infobar in the USB + dialog below the 'Select USB devices to redirect" label. + Content could probably be improved, but this is a step in the right + direction ;) + + This can be tested with + diff --git a/gtk/usb-device-widget.c b/gtk/usb-device-widget.c + index b1bf090..660ea03 100644 + --- a/gtk/usb-device-widget.c + +++ b/gtk/usb-device-widget.c + @@ -220,6 +220,11 @@ static GObject *spice_usb_device_widget_constructor( + G_CALLBACK(device_error_cb), self); + + devices = spice_usb_device_manager_get_devices(priv->manager); + + if (devices) { + + g_ptr_array_unref(devices); + + devices = NULL; + + } + + + if (!devices) + goto end; + +2012-09-25 Hans de Goede + + Deal with libusbredirparser.pc rename to libusbredirparser-0.5.pc + The usbredir 0.5 release introduced the new API for 64 bit packet ids, but + it kept the libusbredirparser.pc name as is, meaning that older versions of + qemu will still have their pkg-config check for usbredirparser fulfilled, + and build with the usb-redir device. Due to the API change there will be + some compiler warnings, but the build will succeed, however the usb-redir + device will be broken on 32 bit machines. + + To solve this, the usbredir-0.5.2 release renames the libusbredirparser.pc + file to libusbredirparser-0.5.pc, so that it will no longer fulfill the + pkg-config check of the qemu-1.2 and older releases, stopping the (silent) + breakage. + + spice-gtk does not use the changed parts of the API, but does + use libusbredirparser for the usbredirfilter* functions. This patch adapts + spice-gtk's configure to accept both the libusbredirparser-0.5 and the + libusbredirparser pkg-config names. + +2012-09-25 Marc-André Lureau + + G_GNUC_DEPRECATED_FOR must be defined publicly + It's not enough to define G_GNUC_DEPRECATED_FOR in glib-compat.h, + since this header is not public. Instead, let's define our own + public SPICE_DEPRECATED_FOR macro, and clean-up double definition. + +2012-09-24 Dunrong Huang + + spicy: Make "CopyToGuest" and "PasteFromGuest" insensitive if spice agent is not connected + "CopyToGuest" and "CopyToGuest" can not work if spice agent is not + connected, e.g. guest does not install or enable spice agent, or spice + server does not create vdagent channel. + + In these cases, make those item insensitive. + +2012-09-21 Christophe Fergeau + + Update spice-common submodule + + Update git.mk to latest version + +2012-09-20 Christophe Fergeau + + Update NEWS + + Unescape SpiceSession::uri component by component + Unescaping the whole URI and then parsing it is dangerous as + the unescaping may (for example) add some extra '/' in the URI + which are not part of a path. It's better to do the unescaping later + once the URI has been split in separate components. + This commit unescapes the path, host and query values. Handling escaped + query values is important for usernames/passwords which might contain + chars which are invalid in URIs. + If the host is enclosed in [], it's intentionally not escaped as this + contains an ipv6 URI, and may contain a %zone_id (see RFC4007). This is + consistent with libvirt/libxml2 behaviour, not with what gvfs does. + +2012-09-14 Colin Walters + + usb-acl-helper: Clear environment + Otherwise we can be subject to attack via environment variables such + as DBUS_SYSTEM_BUS_ADDRESS. + This addresses CVE-2012-4425 http://seclists.org/oss-sec/2012/q3/470 + +2012-09-13 Christophe Fergeau + + cursor: don't access unitialized data when logging + SpiceCursor::header is only valid when SPICE_CURSOR_FLAGS_NONE is + not set in SpiceCursor::flags, so don't try to log info about + the header before we have tested this flag. + +2012-09-12 Christophe Fergeau + + channel: Introduce CHANNEL_DEBUG for channel debug logs + It automatically prepends the channel name to the log message + for easier debugging. + + Fixes rhbz#822437 + +2012-09-10 Christophe Fergeau + + build-sys: Fix symbol versioning + My changes in bug 5bf72a2e had a typo which broke symbol versioning + of libspice-client-gtk.so when -Wl,--version-script is available... + + Update spice-common submodule + We need a newer spice-protocol to get the definitions for A8 surfaces. + Without it, compilation is broken. + + Fix VD_AGENT_HAS_CAPABILITY use + The 'size' argument to this macro (defined in + spice-protocol/spice/vd_agent.h) is the number of 32 bit elements + available in its first argument. In channel-main.c it's used + most of the time with SpiceMainChannelPrivate::agent_caps which is + an uint32_t[VD_AGENT_CAPS_SIZE]. The 'size' argument to pass to + VD_AGENT_HAS_CAPABILITY is thus the number of elements in this array, + and not sizeof(agent_caps). + + Fixes rhbz#837545 + +2012-09-07 Søren Sandmann Pedersen + + Advertise SPICE_DISPLAY_CAP_A8_SURFACE + +2012-09-06 Christophe Fergeau + + build: Add fallback symbol files to EXTRA_DIST + +2012-09-05 Uri Lublin + + spicy: add --title= command line option + + Revert "spice-common removed" + This reverts commit 519f118c7786aa0c16cd2a5f216b52cea4ac42d5. + + spice-common removed + +2012-09-03 Alexander Larsson <alexl@redhat.com> + + Fix region leak in gtk2 compat defines + https://bugs.freedesktop.org/show_bug.cgi?id=54277 + +2012-09-02 Søren Sandmann Pedersen <ssp@redhat.com> + + Advertise SPICE_DISPLAY_CAP_COMPOSITE + + Add support for Composite command + All the real work is done in spice-common, so this is a pretty simple + change. + + Conflicts: + spice-common + +2012-08-31 Alexander Larsson <alexl@redhat.com> + + Make region code build with gtk2 + https://bugs.freedesktop.org/show_bug.cgi?id=54277 + +2012-08-31 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix X11 backend + The X11 backend allocates the "image" with X11 and needs the widget to + be realized before calling spicex_image_create(). + + https://bugs.freedesktop.org/show_bug.cgi?id=54310 + + Update SpiceDisplay:only-downscale documentation + +2012-08-31 Alexander Larsson <alexl@redhat.com> + + Fix flickering regression on some systems + For some reason the way we remove the "inner" area + when clearing the background doesn't work on one computer. + I don't really know why, but the current approach does seems a + little fragile. + + This replaces it with a solid region operation that works on + all my machines. + + https://bugs.freedesktop.org/show_bug.cgi?id=54277 + +2012-08-30 Alexander Larsson <alexl@redhat.com> + + Add only_downscale property + When this is enabled we never scale displays larger + than their actual size. + + https://bugs.freedesktop.org/show_bug.cgi?id=54277 + + Centralize scaling handling + This moves all the handling of scaling calculations and + positioning of the display inside the widget into one place. + + This makes it easier to later change how scaling works. + + Also, the new scaling only support aspect-ratio-keeping + scaling. + + https://bugs.freedesktop.org/show_bug.cgi?id=54277 + +2012-08-30 Christophe Fergeau <cfergeau@redhat.com> + + Move AM_PROG_AR before LT_INIT call + The other way round generates warnings: + configure.ac:14: warning: LT_INIT was called before AM_PROG_AR + aclocal.m4:1015: AM_PROG_AR is expanded from... + +2012-08-29 Alon Levy <alevy@redhat.com> + + support automate >= 1.12 with new required AM_PROG_AR + +2012-08-29 Marc-André Lureau <marcandre.lureau@redhat.com> + + Update spice-common + +2012-08-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + glib-compat: add G_GNUC_DEPRECATED_FOR + G_GNUC_DEPRECATED_FOR was introduced in glib 2.26 + + misc build fix when --disable-smartcard + + widget: differentiate key press & release from press only events + Until now, Spice clients only sent separate key events for press and + release. But this may result in unwanted key repetition from guest VM + side. It seems OSes have various implementations. While MS Windows + relies on hardware key repeats (which are several sequential press + events), otoh, X11 uses software key repeat (although not Linux + keyboard/VT by default). + + We can't easily disable guest side repeaters, as it may be enforced by + other components (a X11 client can adjust each key individually, or + the desktop settings may change it etc.). Neither can we rely only on + guest software repeater as Windows doesn't seem to have one by + default, so we need to keep sending multiple press events as of today. + + It seems a nice way to improve the situation is to send a single + "press&release" key event when the user released the key within a + short delay. If the key is pressed for longer, we keep the existing + behaviour which has been working pretty well so far, sending separate + "press", then repeatedly "press", and an ending "release" event. + + v2: + - fix some commit message spelling spotted by Alon & Christophe + - simplify a bit the timer handling code after Hans review + - remove the submodule change (will be updated in earler patch once + pushed upstream) + + widget: add keypress-delay property + The delay before the press event is sent to the server if the key is + kept pressed. If the key is released within that time, that delay is + ignored and a single key-press-release event will be sent. + + widget: give more context to send_key() + - use a more explicit SendKeyType enum + - if the key is a modifier key, we don't want to delay press event + + v2: fix compilation (remove down usage) + + inputs: add spice_inputs_key_press_and_release() + If the server is capable of SPICE_INPUTS_CAP_SCANCODE, then we send + can send a single message with key press and release, to avoid + unwanted guest side key repeatition due to network jitter. + + If the server is not capable, spice-gtk will use some compatibility + mode and send the existing DOWN and UP key events seperately. + + util-priv: factor out spice_make_scancode() + Factor out the keyboard scancode manipulation function, to be reusable + by newer code. + + Update spice-common + +2012-08-28 Yonit Halperin <yhalperi@redhat.com> + + channel-smartcard: do not attach temporary migration channel to smartcard + During migration, the smartcard channel that belongs to the temporary + copied session shouldn't be active. + + migration: copy enable-smartcard/audio/usbredir state to the migrated session + Otherwise, we will not create smartcard/usb channel on the destination + side, and we will create audio channels, no matter if they existed + of didn't exist for the src side. + + seamless migration: don't reset messages data when swapping channels + When swapping the src and dest channels's, we need to keep + the xmit_queue and msg serials. Their state is expected to stay the same + after migration. + + seamless migration: transfer pending msgs to the destination, instead of sending them to the src before FLUSH_MARK + In order to save migration time, and probably also decrease migration + data size, we push the flush mark to the src server before any other + message. All the other pending msgs will be sent later to the + destination server (see next patch). + + seamless migration: src and dest servers handshake + Flow: + (1) *src* main channel coroutine (main_handle_migrate_begin_seamless): + handles SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS; yields to the main loop, + supplying it the destination information needed for connection. + (2) main context (migrate_connect): + Establishes a new session for connecting to the destination. + After all the channels are opened (async), their state, except for + the one of the main channel, is modified to + SPICE_CHANNEL_STATE_MIGRATING (see migrate_channel_event_cb); + no reading is done from the channel during this state. + The dest main channel's state is changed to SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE + + (3) *dest* main channel coroutine: sends to the dest server SPICE_MSGC_MAIN_MIGRATE_DST_DO_SEAMLESS + (see spice_channel_recv_auth) + (4) *dest* main channel coroutine: recevices SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK/NACK. + adds main_migrate_handshake_done to the main loop. + (5) main context: when all the dest session channels are connected, and the main channel handshake + is done, we yield to the src main channel coroutine (see + migrate_channel_event_cb and main_migrate_handshake_done) + (6) *src* main channel coroutine: sends to the src server + SPICE_MSGC_MAIN_MIGRATE_(CONNECTED|CONNECTED_SEAMLESS|CONNECT_ERROR) + + For more details see spice-protocol. commit + 1ad5d259cb4b695ec3106de7ccd082e031e7ae11 + + seamless-migration: update spice-common submodule + Update channel-main as well to support the change made to + SpiceMsgMainMigrationBegin: it now holds all the destination fields + inside SpiceMigrationDstInfo. + + channel_main: handle SPICE_MSG_AGENT_CONNECTED_TOKENS + + channel-base: remove bad check of SpiceMsgWaitForChannels validity + SpiceMsgWaitForChannels is not packed. Comparing the original + msg size to SpiceMsgWaitForChannels is wrong. + +2012-08-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + Update spice-common + + Release v0.13 + +2012-08-26 Dunrong Huang <riegamaths@gmail.com> + + spicy: connect from cli only if hostname and port are provided + This patch will fix following error: + $ spicy --spice-debug + ...... + (spicy:21981): GSpice-DEBUG: spice-session.c:1618 new main channel, switching + (spicy:21981): GSpice-DEBUG: spice-gtk-session.c:811 Changing main channel from (nil) to 0x8534b0 + (spicy:21981): GSpice-DEBUG: spicy.c:1587 new channel (#0) + (spicy:21981): GSpice-DEBUG: spicy.c:1590 new main channel + (spicy:21981): GSpice-DEBUG: spice-channel.c:2255 Open coroutine starting 0x8534b0 + (spicy:21981): GSpice-DEBUG: spice-channel.c:2098 Started background coroutine 0x853538 for main-1:0 + (spicy:21981): GSpice-DEBUG: spice-channel.c:2122 connection failed, trying with TLS port + (spicy:21981): GSpice-DEBUG: spice-channel.c:2126 Connect error + GSpice-Message: main channel: failed to connect + ...... + + When user starts spicy without any command-line arguments, spicy + should not attempt to connected to server automatically because + hostname or port are unknown at the moment. + + What this patch changes is to show the dialog window instead of + connecting to server automatically if no hostname or port are found. + +2012-08-10 Christophe Fergeau <cfergeau@redhat.com> + + Check --spice-disable-effects parameter validity + When --spice-disable-effects is used, error out unless this is + the name of one of the effects we can disable. + + Fixes rhbz#818848 + + Check --spice-color-depth parameter validity + When --spice-color-depth is used, error out unless the color depth + is 16 or 32. + + Fixes rhbz#818847 + +2012-08-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + Update spice-common + +2012-08-08 Christophe Fergeau <cfergeau@redhat.com> + + build: make spice-controller.pc installation conditional + It shouldn't be installed when controller support is disabled. + + build: generate sym-file + When -Wl,--version-script is not available, we fallback to using + libtool --export-symbols feature, but the needed sym-file is missing + from git. This commit adds generation of the sym-file to the + update-map-file Makefile target, and adds a sym-file to git. + The linker on OSX Lion doesn't like to have non-existing symbols + specified in the symbol files it's given, so the symbols need to + be split in glib symbols and gtk symbols. + +2012-08-07 Christophe Fergeau <cfergeau@redhat.com> + + build: add --enable-smartcard=auto support + Currently, when running configure with no arguments, smartcard + support is enabled by default, and configure will fail if it cannot + find libcacard. This commit adds a --enable-smartcard=auto mode to + configure which will use automatically enable smartcard support if + libcacard is available, but it will be silently disabled if libcacard + is not available. Passing --enable-smartcard will fail if libcacard + is not available. Passing --disable-smartcard will always disable + smartcard support and will not test for libcacard availability. + + build: make controller build optional + Apart from the Vala bindings, this is the only part of spice-gtk + which requires Vala to be built from git. Since it's only useful + when spice-gtk is used in conjunction with an oVirt browser plugin, + letting people disabling it will not necessarily cause issues. + +2012-08-05 Matthias Clasen <mclasen@redhat.com> + + Don't use GDK_THREADS_ENTER/LEAVE + These macros have been deprecated. The quick fix for now is to just use the + functions gdk_threads_enter/leave instead. They are deprecated as well, but + deprecated functions don't cause the build to fail (unless you use -Werror). + +2012-07-30 Hans de Goede <hdegoede@redhat.com> + + Remove "usbredirhost: " prefix from usbredirhost error messages + libusbredirhost prefixes all its messages with "usbredirhhost: ", which + is useful when logging to stderr, but not so much when showing the error + to the user in an error dialog, so remove the "usbredirhost: " prefix + when we store the message in a GError. + +2012-07-28 Hans de Goede <hdegoede@redhat.com> + + channel-display: Set monitors_max to 1 on init + This fixes remote-viewer with the new multi monitor support not working + when connecting to a spice-server without the new multi-monitor support. + + Before this fix remote-viewer would hit the following g_return_if_fail: + (remote-viewer:24787): remote-viewer-CRITICAL **: + virt_viewer_session_spice_display_monitors: + assertion `monitors->len <= monitors_max' failed + + spice-widget: release mouse grab on keyboard-grab-inhibit + The purpose of the keyboard-grab-inihbit mechanism is to allow other apps + to grab the input while the spice-widget has the focus, mainly when we're + going to invoke policykit for usb-redirection, as that the policy-kit + agent may want to grab the input. + + Before this patch we were only inhibitting the keyboard grab, which works fine + for vms which are in client mouse mode, but is not enough for vms which are + in server mouse mode. + + This patch also releases the mouse grab on keyboard-grab-inhibit, fixing + the policykit dialog not showing (and thus usb redir not working) when + running with server mouse mode. Note that this makes the inhibit-keyboard-grab + name of the property no longer really cover what it does, but allas it is + part of our ABI... + +2012-07-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + Run-time check monitor per display count <= 256 + Limit range of monitors, to avoid potential crashes lead by invalid + received MonitorConfig values (could be misconfigured or misbehaving + guest) + + This is a a client-side implementation limitation. Eventually, the + range could be inscreased (or unlimited == 0) in the future... + +2012-07-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + Enable the display early when the widget is created + The spice_main_set_display_enabled() function is used to mark the + display/monitor config as enabled. In order to simplify client + implementation, the widget enables the matching display automatically + when the channel mark is received. This is only for legacy reason, and + my lack of understanding at that time. It could as well be enabled + earlier, when the widget is created. It wasn't really a good decision + to disable monitor when the mark is off, which can be toggled when the + primary surface is resize for example, and can cause some races.. + + Add SpiceDisplay:ready property + There are several condition to meet in order to have a widget ready to + be displayed: the monitor must exist, the area must intersect, and the + display mark must be reached. This property will help clients to know + when the widget display is ready. Until now, it was relying on the + channel mark signal only, and had to deal with the rest of the + conditions without much help. + + Handle MonitorsConfig::max_allowed + + main: send monitor config immediately + The only way this can be called currently is via the main/system + coroutine. Remove display timer if any. + + Implement simple monitors alignment + + widget: use display monitors configuration + Use display::monitors property to manage display area. Call + update_area_monitor() to update the widget area depending on monitor + configuration + + spicy: disable display when deleting window + + spicy: learn to deal with monitors + + Make-up a MonitorConfig if the server doesn't provide one + This allows easier compatibility for clients that don't have to + check and interact differently depending on channel capabilities. + + Handle SPICE_MSG_DISPLAY_MONITORS_CONFIG + + Don't attempt to draw an invalid area + If we don't intersect, the area is invalid or of size 0. + + Use monitor_id to compute display_id + + Document spice_main_send_monitor_config() + + widget: don't forget to disconnect all signals handlers + We forgot about display-mark. Use spice_g_signal_connect_object() + helper, which will disconnect properly in all circunstances. + + spice_channel_connect() success if state >= CONNECTING + We may have several widget trying to re-connect the channels now. + It is fine to return successfully if we are already connecting or + connected. + + widget: add monitor property with ctor + + Claim SPICE_DISPLAY_CAP_MONITORS_CONFIG + + Add spice_display_get_primary() + + display: add readonly monitors property + + glib-compat: add g_clear_pointer + A helpful macro from glib 2.34 + + Change surface_id to a guint32 + That's the correct type used by the protocol. + + widget: add main channel before other channels + Make sure that the d->main channel member can be referenced when + adding further channels, when we perform their setup. + + Add missing agent cap description + + display: learn to restrict display to an area + Each spice widget can now restrict the area of the primary + surface they show and interact with by setting the private + area member. + + A nice clean-up would be to seperate an area object that + would deal with clipping, input translation and color + conversion, but the resulting code would be similar anyway + + widget: simplify redraw call + + Update spice-common + +2012-07-16 Uri Lublin <uril@redhat.com> + + usb-device-manager: mingw: connect: cleanup device if it's libdev is missing + For Windows client, when connecting a device to the guest, if a libusb + device (libdev) does not exist, cleanup and forget about that device. + + Most likely, the device was plugged out at driver installation + time, and its remove-device event was ignored. + +2012-07-12 Yonit Halperin <yhalperi@redhat.com> + + migration/channel-inputs: reset motion count after migration + The motion count must stay synchronized with the server, otherwise, + it is possible that we will stop sending motion events to the server + after migration. + + rhbz#835997 + +2012-07-11 Uri Lublin <uril@redhat.com> + + usb-device-manager: do not try to connect a usb device that was removed + If a device that is asked to be shared with the guest, is unplugged out + of the machine before being redirected, then let the user know that + usbredir of that device failed (and cleanup nicely). + + For Windows client, the time between request and redir is larger, as + it includes the time it takes to install the libusb driver. + +2012-07-11 Marc-André Lureau <marcandre.lureau@redhat.com> + + usbutil: be more explicit about usbids_vendor_count usage + I introduced a regression in the previous patch, counting the + usbids_vendor_count from -1 if the previous attempt failed. + + usbutil: fix crash on windows + vendor_count is the last access index, the actually count is +1. + + On Windows, it crashes later on because of corrupted memory. + + Thanks to valgrind for this precious help: + + ==4535== Invalid write of size 2 + ==4535== at 0x40197E: spice_usbutil_parse_usbids (usbutil.c:170) + ==4535== by 0x401CEC: spice_usbutil_load_usbids (usbutil.c:241) + ==4535== by 0x4020C6: main (usbutil.c:322) + ==4535== Address 0x56b740c is 12 bytes after a block of size 348,160 alloc'd + ==4535== at 0x4A0884D: malloc (vg_replace_malloc.c:263) + ==4535== by 0x4EAAEBE: g_malloc (gmem.c:159) + ==4535== by 0x401847: spice_usbutil_parse_usbids (usbutil.c:156) + ==4535== by 0x401CEC: spice_usbutil_load_usbids (usbutil.c:241) + ==4535== by 0x4020C6: main (usbutil.c:322) + ==4535== + + usbutil: look up usb.ids under g_get_system_data_dirs() by default + Simplify a little bit the portability by looking up usb.ids file + under g_get_system_data_dirs(). This is how most resources are + found under other OS, looking up files under various places, since + installation location may vary. + +2012-07-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix make distcheck + +2012-07-10 Uri Lublin <uril@redhat.com> + + usb-device-manager: mingw: win driver install callback: add missing ifdef + This fixes the following compilation error message (without USE_USBREDIR): + + usb-device-manager.c:183:13: error: 'spice_usb_device_manager_drv_install_cb' declared 'static' but never defined [-Werror=unused-function] + + win-usb-driver-install: initialize "req" with memset + This fixes the following compilation error message: + + ../../gtk/win-usb-driver-install.c: In function 'spice_win_usb_driver_send_request': + ../../gtk/win-usb-driver-install.c:187:5: error: missing braces around initializer [-Werror=missing-braces] + ../../gtk/win-usb-driver-install.c:187:5: error: (near initialization for 'req.hdr') [-Werror=missing-braces] + + usb-device-manager: mingw: ignore "remove" udev event when un/installing a driver + + usb-device-manager: mingw: keep driver install/uninstall state of a device + Currently only driver install/unsinstall is of interest, such that + extra udev events can be ignored. + + usb-device-manager: add 'state' field to SpiceUsbDeviceInfo + To be used on Win32 to ignore extra udev events + received during driver install/uninstall. + + Win32/mingw: win-usb-dev: skip hubs + also skip devices with bad (0) device-address. + + Win32/mingw: usb-device-manager: uninstall win usb driver upon device disconnect + + win-usb-driver-install: add capability to remove (uninstall) a win usb driver + + Windows mingw: usb: Dynamically install a libusb driver for USB devices + - Added win-usb-driver-install.[ch] + - Added win-usb-clerk.h + + Operation (on Windows, spice-gtk point of view): + - After some sanity checks, just before redir'ing a USB device + a libusb driver needs to be installed (before libusb can open the device) + - A connection (NamedPipe) is established with usb-clerk, a libusb + driver installation service, and a request for driver installation + is sent. + - Installation status is asynchronously read from the pipe, and + spice_usb_drv_install_finished() is called. + - Upon a successful intallation, usbredir continues. + + Linux operation is not changed. + +2012-07-10 Arnon Gilboa <agilboa@redhat.com> + + Windows mingw: usb: implement GUdevDevice & GUdevClient for windows + - Added win-usb-dev.[ch] + - Added GUdevDevice and GUdevClient like classes + - Added uevent signal based on WM_DEVICECHANGE + +2012-07-10 Uri Lublin <uril@redhat.com> + + Make SpiceUsbDevice a box for SpiceUsbDeviceInfo, instead of a box for libusb_device + Note that this change may affect performance a bit, as sometimes there is + a need to find the libusb_device or the SpiceUsbDevice. Likely it's negligible. + + Introduce SpiceUsbDeviceInfo to be kept instead of a libusb_device + For Windows, it's better not to keep references for libusb_devices + that are not used. + So instead of makeing SpiceUsbDevice a box for a libusb_device + it is going to be a box for a SpiceUsbDeviceInfo. + + Windows mingw: usb: configure.ac: do not require GUDEV for USBREDIR + For windows GUDEV is not required + For Linux GUDEV is checked as a part of USBREDIR block, but + as a separate check. + + usb-device-manager: mingw: add_dev: ignore already known devices + Sometimes on a Windows client, udev events are received while + the driver is being un/installed. so just ignore it + + usb-device-manager: add a helper function to find a usb device <bus, addr> + And use it in spice_usb_device_manager_remove_dev + + spice_usb_device_get_description: use device-descriptor only to get <vid,pid> + In preparation for a different SpiceUsbDevice. + + With the new SpiceUsbDeviceInfo, <vid,pid> will be provided by + SpiceUsbDevice, and not by the device_descriptor (from libusb) + + spice_usb_device_manager_device_error: replace SpiceUsbDevice with libusb_device + Its only user is channel-usbredir, which needs the libusb_device. + + In preparations for a different SpiceUsbDevice. + + spice_usb_device_manager_auto_connect_cb: use type SpiceUsbDevice for "device" + Currently SpiceUsbDevice is a BOX for libusb_device. + In preparation for a different SpiceUsbDevice. + + spice_usb_device_manager_add_dev: use type SpiceUsbDevice for "device" + Currently SpiceUsbDevice is a BOX for libusb_device. + In preparation for a different SpiceUsbDevice. + + Renamed the libusb_device variable to libdev. Needed when + asking usbredir to check the filter. + + spice_usb_device_manager_add_dev: check auto_ok before freeing libusb device list + In preparation for a different SpiceUsbDevice. + + spice_usb_device_manager_remove_dev: use type SpiceUsbDevice for "device" + Currently SpiceUsbDevice is a BOX for libusb_device. + In preparation for a different SpiceUsbDevice. + + controller/test.c: mingw: fix compiler bad param warning for ReadFile + It seems that ssize_t is int, while DWORD is long + + Compiler warning (some whitespaces where added for readability): + ../../../gtk/controller/test.c: In function 'read_from_pipe': + ../../../gtk/controller/test.c:108:5: warning: passing argument 4 \ + of 'ReadFile' from incompatible pointer type [enabled by default] + In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/windows.h:70:0, + from ../../../gtk/controller/test.c:27: + /usr/i686-w64-mingw32/sys-root/mingw/include/winbase.h:1426:29: note: expected \ + 'LPDWORD' but argument is of type 'ssize_t *' + + usb-device-manager: warn if a device to remove was not found + Also changed a bit the warning text on device-add to differentiate the two. + + spicy: more informative presentation of usb devices in menu + Using the default format. + +2012-07-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + controller: async flush read/write + Windows namedpipes behave a bit differently from Unix socket, and may + return incomplete read/write. By using 2 read/write() helpers, try to + complete the operation before returning. Since the IO operation may be + splitted over several call, we make sure the buffer pointer is on the + heap. We use exception for EOF or BROKEN_PIPE condition, which also + simplifies the code. + + To really work with namedpipe, the giowin32streams need to be fixed as + well to handle concurrent read & write properly, see for details: + https://bugzilla.gnome.org/show_bug.cgi?id=679288 + + Remove mandatory generation of vala debug C + Use make VALAFLAGS=-g if you need it instead + +2012-07-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix mingw build + printf is redefined by glib/gi18n.h + + In file included from ../spice-common/common/spice_common.h:29:0, + from ../spice-common/common/ring.h:23, + from spice-channel-cache.h:23, + from spice-session-priv.h:26, + from desktop-integration.c:29: + ../spice-common/common/log.h:49:17: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + ../spice-common/common/log.h:56:16: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + In file included from ../spice-common/common/canvas_base.h:25:0, + from decode.h:23, + from spice-session-priv.h:27, + from desktop-integration.c:29: + ../spice-common/common/lz.h:22:5: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + ../spice-common/common/lz.h:23:5: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + ../spice-common/common/lz.h:24:5: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + + unused variable 'self' if !USE_USB + CC spice-widget-enums.lo + desktop-integration.c: In function 'spice_desktop_integration_dispose': + desktop-integration.c:175:30: error: unused variable 'self' + [-Werror=unused-variable] + +2012-07-06 Hans de Goede <hdegoede@redhat.com> + + spice-widget: Don't change usbredir/automount settings while redirecting + The keyboard focus may change while usb-device-manager is in the process of + redirecting a usb-device (as this may show a policykit dialog). Making + autoredir/automount setting changes while this is happening is not a good idea! + + Since usb-device-manager already sets keyboard_grab_inhibit when it is + redirecting to allow the policykit dialog to show, we can use that to + inhibit usb-autoredir setting changes. + + spice-gtk-session: hookup automount inhibiting + Inhibit automounting when usb-autoredirection is active. + + Add a desktop-integration helper class + We need to integrate closely with the desktop environment of the user in + several cases. Some examples are disabling auto-mounting when auto-usbredir + is active (rhbz#812972), and disabling the screensaver when fullscreen + (fdo#34793). + + Unfortuntely these kinds of things require desktop environment specific + handling. Therefor this patch introduces a desktop-integration helper class, + which is to server as a container for all sort of desktop environment specific + functions. + + For now it just supports disabling automounting under Gnome, but this will be + extended in the future. + +2012-06-28 Yonit Halperin <yhalperi@redhat.com> + + agent: fix mishandling of SPICE_MSG_MAIN_AGENT_TOKEN + Add the given tokens instead of overriding the existing ones. + +2012-06-26 Hans de Goede <hdegoede@redhat.com> + + spice-gtk-session: rename update_keyboard_focus to request_auto_usbredir + To better reflect what then function does, also rename the tracking variable + inside spice-gtk-session to match. + + spice-gtk-session: Fix keyboard focus tracking + This patch changes the "do we have focus?" tracking, to keeping a counter with + how many widgets have focus. The reason for this is that sometimes multiple + spice-widgets can have focus at the same time, yes really! Sometimes (rarely, + hard to reproduce) the focus in event for one window arrives before the + focus out of the other window. + + spice-gtk-session: Only update usb "auto-connect" when doing "auto-usb-redir" + Only update the UsbDeviceManager's "auto-connect" property when + "auto-usb-redir" is set, otherwise leave it as is. This allows apps to + control UsbDeviceManager's "auto-connect" directly, without it getting reset + on every keyboard focus change. + +2012-06-24 Uri Lublin <uril@redhat.com> + + Move "err" variable definition to beginning of the function + This fixes the following compilation error: + channel-usbredir.c: In function 'spice_usbredir_channel_connect_device_async': + channel-usbredir.c:313:9: error: jump skips variable initialization [-Werror=jump-misses-init] + +2012-06-13 Christophe Fergeau <cfergeau@redhat.com> + + Fix build when usbredir is disabled + I broke it with my leak fixes + + Fix various memory leaks + ==25063== 12,827 (2,032 direct, 10,795 indirect) bytes in 127 blocks are definitely lost in loss record 9,477 of 9,502 + ==25063== at 0x4A0884D: malloc (vg_replace_malloc.c:263) + ==25063== by 0x3DE384D2BE: g_malloc (gmem.c:159) + ==25063== by 0x3DE38616B1: g_slice_alloc (gslice.c:1003) + ==25063== by 0x3DE38346B0: g_error_new_valist (gerror.c:393) + ==25063== by 0x3DE3834A8C: g_set_error (gerror.c:560) + ==25063== by 0x3DE4871108: g_socket_receive_with_blocking (gsocket.c:2513) + ==25063== by 0x5B708E8: bio_gsocket_bread (bio-gsocket.c:56) + ==25063== by 0x61AEBD8: BIO_read (bio_lib.c:212) + ==25063== by 0x5ECAC5B: ssl3_read_n (s3_pkt.c:238) + ==25063== by 0x5ECBD3D: ssl3_read_bytes (s3_pkt.c:318) + ==25063== by 0x5ECD6CF: ssl3_get_message (s3_both.c:426) + ==25063== by 0x5EC5AFB: ssl3_get_new_session_ticket (s3_clnt.c:1822) + + ==25063== 90 bytes in 3 blocks are definitely lost in loss record 7,354 of 9,502 + ==25063== at 0x4A0884D: malloc (vg_replace_malloc.c:263) + ==25063== by 0x3DE384D2BE: g_malloc (gmem.c:159) + ==25063== by 0x3DE3862D0B: g_strdup (gstrfuncs.c:356) + ==25063== by 0x5B961B5: spice_usb_device_manager_set_property (usb-device-manager.c:306) + ==25063== by 0x3DE40148FB: g_object_constructor (gobject.c:1352) + ==25063== by 0x3DE4015D70: g_object_newv (gobject.c:1713) + ==25063== by 0x3DE401655F: g_object_new_valist (gobject.c:1830) + ==25063== by 0x3DE485924D: g_initable_new_valist (ginitable.c:224) + ==25063== by 0x3DE4859348: g_initable_new (ginitable.c:148) + ==25063== by 0x5B97330: spice_usb_device_manager_get (usb-device-manager.c:770) + ==25063== by 0x52D8C6B: spice_gtk_session_update_keyboard_focus (spice-gtk-session.c:845) + ==25063== by 0x52D6DC1: spice_gtk_session_set_property (spice-gtk-session.c:238) + + ==25063== 120 bytes in 3 blocks are definitely lost in loss record 8,448 of 9,502 + ==25063== at 0x4A06F18: calloc (vg_replace_malloc.c:566) + ==25063== by 0x68BB2E5: usbredirfilter_string_to_rules (usbredirfilter.c:54) + ==25063== by 0x5B96123: spice_usb_device_manager_set_property (usb-device-manager.c:293) + ==25063== by 0x3DE40148FB: g_object_constructor (gobject.c:1352) + ==25063== by 0x3DE4015D70: g_object_newv (gobject.c:1713) + ==25063== by 0x3DE401655F: g_object_new_valist (gobject.c:1830) + ==25063== by 0x3DE485924D: g_initable_new_valist (ginitable.c:224) + ==25063== by 0x3DE4859348: g_initable_new (ginitable.c:148) + ==25063== by 0x5B97330: spice_usb_device_manager_get (usb-device-manager.c:770) + ==25063== by 0x52D8C6B: spice_gtk_session_update_keyboard_focus (spice-gtk-session.c:845) + ==25063== by 0x52D6DC1: spice_gtk_session_set_property (spice-gtk-session.c:238) + ==25063== by 0x3DE40148FB: g_object_constructor (gobject.c:1352) + + ==25063== 11,959 (72 direct, 11,887 indirect) bytes in 1 blocks are definitely lost in loss record 9,475 of 9,502 + ==25063== at 0x4A06F18: calloc (vg_replace_malloc.c:566) + ==25063== by 0x3459C92DDC: XkbGetKeyboardByName (XKBGetByName.c:59) + ==25063== by 0x52DF000: vnc_display_keymap_gdk2xtkbd_table (vncdisplaykeymap.c:153) + ==25063== by 0x52D9FA6: spice_display_init (spice-widget.c:389) + ==25063== by 0x3DE402FA05: g_type_create_instance (gtype.c:1892) + ==25063== by 0x3DE40147A7: g_object_constructor (gobject.c:1849) + ==25063== by 0x52DA07B: spice_display_constructor (spice-widget.c:412) + ==25063== by 0x3DE4015D70: g_object_newv (gobject.c:1713) + ==25063== by 0x3DE401655F: g_object_new_valist (gobject.c:1830) + ==25063== by 0x3DE4016893: g_object_new (gobject.c:1545) + ==25063== by 0x52DE746: spice_display_new (spice-widget.c:1924) + ==25063== by 0x41D6C3: virt_viewer_display_spice_new (virt-viewer-display-spice.c:219) + +2012-06-11 Marc-André Lureau <marcandre.lureau@redhat.com> + + misc: use g_value_dup_object + + Fix incorrect format string + + Fix video playback with GStreamer backend + The playback audio delay is not correctly adjusted, we should take + min_latency, set by gst_bin_do_latency_func (). + + Deprecate spice_channel_set_capability() + This was initially public to eventually let a derived class + implement more capabilities. Even though it is technically + doable to derive and tweak exisiting channels, there is a + lack of support in spice-gtk for doing that. + + Allow to disable specific capabilities at runtime + Capability BAR for channel FOO can be disabled at runtime by setting + the SPICE_FOO_CAP_BAR environment variable to '0' + Disabling capabilities is useful for testing purpose. + +2012-06-11 Christophe Fergeau <cfergeau@redhat.com> + + spice_channel_coroutine: fix function exit in error path + spice_channel_coroutine returns a void *, but one of its error path + is doing 'return FALSE'. This commit replaces this return with a + 'goto cleanup' since this is what is done in the other error paths. + + spice_channel_coroutine: emit signals in all error cases + There are several very unlikely failures where no signal is emitted + to indicate the failure. Since applications rely on these signals + to detect spice-gtk connection failures, it's important to emit + one in all error cases. + +2012-06-10 Christophe Fergeau <cfergeau@redhat.com> + + Emit SPICE_CHANNEL_ERROR_TLS when certificate can't be found + When trying to start remote-viewer with SPICE over TLS with + --spice-ca-file with a wrong filename, the connection fails + but remote-viewer keeps displaying the "Trying to connect" + message. The only hint that something went wrong is: + (remote-viewer:12924): GSpice-WARNING **: loading ca certs from a/home/teuf/foo.crt + + This patch makes sure we emit a SPICE_CHANNEL_ERROR_TLS before + giving up on channel creation to inform the application that + an error happened. + +2012-06-07 Christophe Fergeau <cfergeau@redhat.com> + + build: allow building with newer glibc-headers and -O0 + Fix copied from libvirt, commit by Eric Blake. + + glibc 2.15 (on Fedora 17) coupled with explicit disabling of + optimization during development dies a painful death: + + /usr/include/features.h:314:4: error: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Werror=cpp] + + Work around this by only conditionally defining _FORTIFY_SOURCE, + in the case where glibc can actually use it. The trick is using + AH_VERBATIM instead of AC_DEFINE. + +2012-06-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + Update spice-common + +2012-06-04 Hans de Goede <hdegoede@redhat.com> + + spicy: Change 'OK' button to 'Close' button in USB device selection + The USB device selection applies immediately, so the dialog should be using + 'Close' instead of 'OK' for its primary button. + + This patch syncs spicy with virt-viewer wrt the USB device selection dialog. + +2012-05-29 Marc-André Lureau <marcandre.lureau@redhat.com> + + widget: disconnect session_inhibit_keyboard_grab_changed + There is one handler we forgot to disconnect on dispose() + that may cause a crash. + + I am thinking of generalizing usage of + spice_g_signal_connect_object().. + + Should fix: + https://bugzilla.redhat.com/show_bug.cgi?id=823570 + +2012-05-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + Clipboard clean-up and fixes for Windows client + The Windows client was getting in the way of guest copy-paste, + because when the guest was taking the clipboard grab, the agent + notifies the client, it takes the grab too, and in return + receives clipboard notification of new ownership from the client + clipboard. + + Though we had a hack to check if this new client clipboard event + is caused by us, the Windows Gtk clipboard is giving 2 notifications + for some reasons. + + It turned out there is a much better way than the "selfgrab" hack, + by setting ownership of the clipboard. Problem solved, and cleaner + code! + + https://bugzilla.redhat.com/show_bug.cgi?id=822688 + +2012-05-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + session: correctly track main channel + The main channel can change when we are reconnecting to the server, + for example, when querying the password to the user. From there, + the old main channel is destroyed, but we don't track properly the + new main channel. + + This fix migration crashing later on, because of missing main channel: + https://bugzilla.redhat.com/show_bug.cgi?id=823874 + +2012-05-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + Reset grab-sequence on match + This avoids triggering the grab event on consecutive + matches, such as ctrl+alt (match) then ctrl+alt+foo + (match again) that would prevent the longer combination + from being sent. + + If grab sequence is matched, still send modifier keys + If the last key pressed from the grab sequence is a modifier + key, let send it to the guest too. + + This solves the issue of default grab-sequence being ctrl+alt + and preventing ctrl+alt+del from working. + +2012-05-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + Running out of reserved space, break ABI + The change abc56811de978ad336a651924a21b920cfe677f0 actually added + a field in a public struct while changing overall struct size, the + fields were also reorder, all of this breaks ABI. + + However, we are running out of free space in SpiceChannelClass + struct. And since the SPICE_RESERVED_PADDING was 44 bytes, that is + quite limited on 64bits (only 5 pointers fit). + + I propose we break ABI during this cycle. This means that programs + using spice-gtk will need to be recompiled to use the new library. + (the old library should be parallel installable though). This let us: + - use a better SPICE_RESERVED_PADDING based on pointer size, since + it is what is usually added for virtual methods + - reset the amount taken from the padding in the various struct + - reorder fields a little + - add some missing "priv" pointers + - whatever I am missing that we can still change before next release + + Please comment if I am missing something, or correct me + + session: correctly set and unset ssl-verify flags + If no cert-subject or pubkey is provided, we should unset the corresponding flags. + +2012-05-17 Yonit Halperin <yhalperi@redhat.com> + + record channel: reseting channel caps + + playback channel: reseting channel caps + + display channel: reseting channel caps + + main channel: reseting channel caps + + Fix not setting channel specific capabilities upon channel reset + Related: rhbz#821795 + + The capabilities have been zeroed after channel reset, which have lead to + publish the wrong caps when both port and tls-port are given, and the + channels are secured (first attempt to connect the channel with "port" + has failed; the channel got reset, and then reconnected with "tls-port" + and bad caps). Specifically, the bug causes semi-seamless migration not + to work when part of the channels are secured. + +2012-05-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + python: fix Spice.Audio binding + The spice_audio_new() function is not correctly generated h2def.py + anymore because of the surrounding #ifdef and macros. Add it in + the manual.defs instead. + + Avoid API breakage: + 2012-05-10 01:56:48,884 (cli:83): Uncaught exception: + Traceback (most recent call last): + File /usr/share/virt-manager/virtManager/console.py, line 475, in + _channel_new_cb + self.audio = spice.Audio(self.spice_session) + TypeError: GObject.__init__() takes exactly 0 arguments (1 given) + + https://bugzilla.redhat.com/show_bug.cgi?id=820335 + +2012-05-03 Yonit Halperin <yhalperi@redhat.com> + + display: video streaming: add support for frames of different sizes + rhbz #815426 + + When playing a youtube video on Windows guest, the driver sometimes sends + images which contain a video frame, but also other parts of the + screen (e.g., the you tube process bar). In order to prevent glitches, we send these + images as part of the stream, using SPICE_MSG_DISPLAY_STREAM_DATA_SIZED. + +2012-05-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix parsing URI query + Do not depend on uninitialized "len" variable to set the query string. + + https://bugzilla.redhat.com/show_bug.cgi?id=818169 + +2012-04-27 Christophe Fergeau <cfergeau@redhat.com> + + g_getenv returns a const string + When switching from getenv to g_getenv, 'doms' declaration + wasn't changed from char * to const char *, which causes + a gcc warning. + +2012-04-27 Daniel P. Berrange <berrange@redhat.com> + + Fix annotations for GrabSequence class + The default transfer mode is wrong for spice_display_get_grab_keys. + The array parameter for spice_grab_sequence_new needs explicit + annotation + +2012-04-26 Daniel P. Berrange <berrange@redhat.com> + + Replace getenv/setenv with g_getenv/g_setenv for Win32 portability + +2012-04-25 Daniel P. Berrange <berrange@redhat.com> + + Fix --spice-debug flag on glib >= 2.31 + With glib >= 2.31 no debug messages are ever printed out by + default, which makes the --spice-debug flag useless. This + fix explicitly turns on the appropriate log domain when + debug is requested. It takes care to preserve the users + own existing log domain requests + +2012-04-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + Release v0.12 + + Lower a few warnings when migration fails + +2012-04-24 Daniel P. Berrange <berrange@redhat.com> + + Fix multiple problems with URI parsing + The URI parsing was not correctly skipping over the path component + if a port number was specified using the traditional URI scheme, + + eg + + spice://somehost:5900/ + + would result in failed parse due to the trailing '/' + + The URI parsing was also not considering that the authority + component is allowed to contain '[' and ']' around the hostname. + This is used when specifying raw IPv6 addresses to remove the + parsing ambiguity wrt ':'. + + eg + + spice://[::1]:5900/ + + Various stages of parsing also failed to report errors. + +2012-04-23 Uri Lublin <uril@redhat.com> + + setsockopt: check for ENOTSUP only if defined + For windows (mingw32) ENOTSUP is not defined. + + Related to 3bfadb8587f59a74d373e26385d348a105c2e425 + +2012-04-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + Allow to disable CELT at runtime + We might want to make it a property, but having an environemnt variable + is useful too, to override behaviour. + + build-sys: pyparsing req. moved to spice-common + +2012-04-19 Daniel P. Berrange <berrange@redhat.com> + + Fix callback signature for --spice-debug option handling + The callback for option handling should return TRUE otherwise the + option parser will think parsing failed. The current 'void' return + type meant it was non-deterministic whether --spice-debug actually + worked or not + +2012-04-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + Clear cache and glz dictionnary on switch-host + If we don't clear the glz dictionnary, this might lead to + corrupted/invalid dictionnary and invalid memory allocation due + unbounded increase of dictionnary size + + Set new cert-subject when switching host + https://bugzilla.redhat.com/show_bug.cgi?id=802574 + + gtk: scroll event are not received with recent gtk+ + Add explicit scroll event mask to make it work again. + +2012-04-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix cursor hide not hiding in some cases + cursor_set() didn't un-hide correctly by setting "show_cursor" to + NULL. + + The code is simplified a bit in server mode case, where the new cursor + will be invalidated and shown during cursor move only, instead of + twice (checked no regression with dual-head server mode) + +2012-04-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix crash when closing while recording + First notify about disconnection before resetting the channel data. + An audio recording task might expect the channel to be in a ready + state otherwise, for example. + + https://bugzilla.redhat.com/show_bug.cgi?id=810247 + +2012-04-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + agent: avoid use of alloca for sending large msg + Instead of allocating unbounded memory and doing extra copy on the + stack, let's just improve our helper function to send messages in + various pieces. + + See also: https://bugzilla.redhat.com/show_bug.cgi?id=809145 + +2012-04-04 Christophe Fergeau <cfergeau@redhat.com> + + autogen.sh: default to --enable-vala when building from git + People using autogen.sh are likely to be building from git, so may + get updates to vala files at any time. Checking for the presence of + controller.vala.stamp to decide whether vala should be enabled or not + is not very accurate since it doesn't reflect if a .vala file needs + to be regenerated or not. + It's better to always pass --enable-vala to configure, it's always + possible to disable it by using --disable-vala as an autogen.sh argument. + + controller: handle USB redirection messages + + autogen.sh: log configure command line + Since --enable-vala may or may not be passed to configure, seeing + the actual command line that was used is helpful. + +2012-04-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + fix build with glib < 2.32 + Reported and verified by Nicolas Prochazka + +2012-04-03 Hans de Goede <hdegoede@redhat.com> + + SpiceDisplay: Fix rounding of mouse motion events with GTK-3.0 + Before this patch we were assuming that the GdkEventMotion value we receive + are always whole (integer) numbers, which is not the case with GTK-3.0. + + SpiceDisplay: Don't try to scale mouse coordinates when we're not scaling + Often (when not resized by the user) even though scaling is enabled, we are + not actually scaling. In this case it is not necessary to scale the + mouse coordinates, and sometimes it is even harmful. + +2012-04-03 Yonit Halperin <yhalperi@redhat.com> + + controller: add support for DISABLE_EFFECTS and COLOR_DEPTH + rhbz #787449 + +2012-03-31 Marc-André Lureau <marcandre.lureau@redhat.com> + + Handle grab-broken event + This fixes the pointer being "trapped" in the center of the screen in + server-side mouse mode. It also correctly inform the client that the + pointer/keyboard is no longer grabbed so it can adjust its UI state + accordingly (remote the "press ctrl+alt to ungrab" messages etc). + + I can reproduce only with RHEVM22 host, and a RHEL6 guest, when + switching consoles. + + widget: fix invalid memory ref after channel is distroyed + When the display channel is destroyed, we disconnect all signals + handlers, but we don't remove the reference on the primary surface + data, and that can lead to crashes in a later expose event, reusing + the canvas surface (ex, if scaling is disabled). Call + primary_destroy() when disconnecting the channel from the widget. + + We now keep the primary surface during channel reset (right after + disconnect for example), so the primary surface can be eventually + recycled, and the widget still holds a valid reference until the + signal is received. The primary surface is ultimately destroyed during + finalize, or if the new primary surface size doesn't match. + + Program received signal SIGSEGV, Segmentation fault. + __memmove_ssse3_back () at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2130 + 2130 lddqu -68(%rsi), %xmm0 + Missing separate debuginfos, use: debuginfo-install gtk2-engines-2.20.2-2.fc15.x86_64 libusb1-1.0.9-0.3.rc1.fc16.x86_64 p11-kit-0.6-1.fc16.x86_64 + (gdb) bt + at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2130 + srclen=<optimized out>, srcinc=4096, destinc=68, height=<optimized out>, + half_order=0) at /usr/include/bits/string3.h:52 + dest_bits_per_pixel=32, req_yoffset=<optimized out>, req_xoffset=0, + image=0x7fffffffb9a0, req=<optimized out>, dpy=0x64a630) at PutImage.c:821 + req_height=<optimized out>, req_width=<optimized out>, y=<optimized out>, + x=0, req_yoffset=<optimized out>, req_xoffset=0, image=0x7fffffffb9a0, + gc=0xa817e0, d=33554452, dpy=0x64a630) at PutImage.c:870 + req_xoffset=0, req_yoffset=<optimized out>, x=0, y=26, req_width=17, + req_height=20, dest_bits_per_pixel=32, dest_scanline_pad=32) + at PutImage.c:908 + image=0x7fffffffb9a0, req_xoffset=0, req_yoffset=0, x=0, y=26, + req_width=17, req_height=20) at PutImage.c:1027 + image=<optimized out>, src_x=0, src_y=0, width=17, height=20, dst_x=0, + dst_y=26) at cairo-xlib-surface.c:1357 + ---Type <return> to continue, or q <return> to quit---c + height=20, width=17, dst_y=26, dst_x=0, src_y=<optimized out>, + src_x=<optimized out>, pattern=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER, + surface=0xb9a650) at cairo-xlib-surface.c:2403 + dst_y=26, dst_x=0, mask_y=0, mask_x=0, src_y=26, src_x=0, + abstract_dst=0xb9a650, mask_pattern=0x0, src_pattern=0x7fffffffc6b0, + op=CAIRO_OPERATOR_OVER) at cairo-xlib-surface.c:2452 + src_pattern=0x7fffffffc6b0, mask_pattern=0x0, abstract_dst=0xb9a650, + src_x=0, src_y=26, mask_x=0, mask_y=0, dst_x=0, dst_y=26, width=17, + height=20, clip_region=0x0) at cairo-xlib-surface.c:2415 + src=0x7fffffffc6b0, mask=0x0, dst=0xb9a650, src_x=0, src_y=26, mask_x=0, + mask_y=0, dst_x=0, dst_y=26, width=17, height=20, clip_region=0x0) + at cairo-surface.c:1802 + traps=0x7fffffffbee0, src=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER, + dst=0xb9a650) at cairo-surface-fallback.c:762 + op=CAIRO_OPERATOR_OVER, dst=0xb9a650, traps=0x7fffffffbee0, + antialias=CAIRO_ANTIALIAS_DEFAULT, clip=0x0, extents=0x7fffffffc600) + at cairo-surface-fallback.c:812 + ---Type <return> to continue, or q <return> to quit---bt + op=CAIRO_OPERATOR_OVER, source=0x7fffffffc6b0, clip=0x0) + at cairo-surface-fallback.c:935 + source=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER, surface=0xb9a650) + at cairo-surface.c:2027 + source=0x7fffffffc6b0, clip=0x7fffffffc7b0) at cairo-surface.c:1993 + at cairo-gstate.c:1049 + at spice-widget-cairo.c:104 + expose=0x7fffffffceb0) at spice-widget-cairo.c:133 + expose=0x7fffffffceb0) at spice-widget.c:885 + return_value=0x7fffffffca60, n_param_values=<optimized out>, + param_values=0x7fffffffcad0, invocation_hint=<optimized out>, + marshal_data=<optimized out>) at gtkmarshalers.c:86 + return_value=0x7fffffffca60, n_param_values=2, + param_values=0x7fffffffcad0, invocation_hint=<optimized out>) + ---Type <return> to continue, or q <return> to quit---c + at gclosure.c:777 + detail=0, instance=<optimized out>, emission_return=0x7fffffffccb0, + instance_and_params=0x7fffffffcad0) at gsignal.c:3584 + signal_id=<optimized out>, detail=0, var_args=<optimized out>) + at gsignal.c:3305 + signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3351 + event=0x7fffffffceb0) at gtkwidget.c:4999 + + mjpeg: fix blue-tinted video stream with old server + The major == 1 uses RGB colorspace for mjpeg streams. + +2012-03-30 Marc-André Lureau <marcandre.lureau@redhat.com> + + session: take pubkey reference in setter + The session assumed it owned a reference to it. + But it didn't get it, and that lead to invalid memory access. + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=802574 + + Be more tolerant on NULL arrays + 2 places where we should be more carreful with NULL arrays, and we can + avoid potential crashes. + +2012-03-29 Hans de Goede <hdegoede@redhat.com> + + usb-device-widget: Call set_active on the toggle_button, not the alignment + Since the gnome HIG-ifying of usb-device-widget.c, the vbox contains + alignments, which in turn contain a toggle_button, so calling + gtk_toggle_button_set_active directly on the vbox-containers childdren is + wrong. + +2012-03-29 Uri Lublin <uril@redhat.com> + + usb-acl-helper: add a missing "break" + +2012-03-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + build-sys: move codegen & proto to spice-common + With this iteration, all the spice_codegen.py/proto/marshaller + generation has been moved to spice-common. + + The spice-common directory will ship spice-protocol, since it's needed + there too to build libspice-common. + + Again, make distcheck passes. Build with mingw & fedora linux. + +2012-03-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + Always release shm of primary surfaces + Always remove shared memory segment of primary surfaces when + destroying its canvas. + +2012-03-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + controllers: signal when a client is connected + + controller: handle SEND_CAD message as a property + + Fix cursor not being shown in client mode in some cases + The following seems to happen: + - cursor-hide (for all cursor/display channels) + - cursor-set (for all cursor/display channels) + + All cursor/display channels receive cursor-set events when the cursor + is changed, however, only current display cursor should be drawn in + server-mode. How to know which display? + + So it will wait until cursor-move to draw it in server-mode on the + right display. + + In the case of client-mode cursor, it doesn't matter since it will + depend on which client display the pointer is, so it can be changed + immediately. + +2012-03-20 Marc-André Lureau <marcandre.lureau@redhat.com> + + build-sys: fix make distclean going twice in vapi dir + Don't use DIST_SUBDIRS, it's not needed anyway. + + build-sys: fix compilation of bindings + Hide symbol from API to fix pygobject. + + Also vapigen chokes on "record" typename + + SpiceClientGtk-3.0.gir:32.55-32.55: error: The type name `Gtk.BoxClass' could not be found <type name="Gtk.BoxClass" c:type="GtkBoxClass"/> + + This seems to be a bug in symbol lookup in vapigen. Using a struct + typedef solves it. + + doc: gtk-doc cleanup + Fix all the unused symbols and a few warnings (a lot left) + + Add SPICE_DISABLE_DEPRECATED guard + + build-sys: improve maintainer clean + + build-sys: use new git.mk + +2012-03-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + Hide cursor when it is on a different screen in server mode + When the cursor shape is changed, all the cursor channels are + updated. The current code assumed that the "set" of the shape should + show the cursor, but it should stay hidden instead. + + Also, when the cursor is hidden, we must invalidate its current + region to redraw display. + + Fix: https://bugzilla.redhat.com/show_bug.cgi?id=804308 + +2012-03-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + Do not grab display widget + We used to gtk_grab_add() after mouse grab to limit the mouse events + to the display. But it isn't necessary if the display has its own + window, since gdk_pointer_grab() will be limited to it. + + Note the widget has the keyboard focus & is focused, so this doesn't + affect keyboard events. + + However, this allows application to keep global accelerators + functionning if they want to (like virt-viewer with custom key + bindings). + + Notify agent-connected property change + + Improve spice_main_set_display_enabled() + Check given display id is within the range of array. + Allows to be call with -1 to turn set all displays. + + Fix non-semi-seamless migration in spicy + The windows are destroyed during non-semi-seamless migrations, but the + gtk session and connected handlers remains. When a property changes + again on it, it will signal a destroyed window and lead to a crash. + + The signal handler should be disconnected when the window is + destroyed. Since we have N numbers of handlers, it's easier to use + spice_signal_connect_object() helper to handle this for us by turning + spice_window structure into a basic GObject. + + That GObject code could be improved, but that wasn't the goal of this + patch. + + Use given color depth in monitor configuration + The main channel only relied on + VD_AGENT_DISPLAY_CONFIG_FLAG_SET_COLOR_DEPTH to set color depth when + connecting to a guest. However, that doesn't seem to be + enough. Instead send given color depth with monitor configuration. + + Fix --spice-color-depth option not "apparently" working. + +2012-03-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + build-sys: if stow is installed, default prefix to it + This is going to make life easier for stow users, including myself. + + build: fix build with glib < 2.32 + Using GMutex as a static mutex is only possible since 2.32. + + Add a G_GNUC_NORETURN to a function that exits + +2012-03-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + use common submodule + + Fix incorrect array size check + +2012-03-14 Marc-André Lureau <marcandre.lureau@redhat.com> + + Move undef FORTIFY below config.h + It used to be below, then was moved on top of all, but now it's + defined in config.h. Hopefully below config.h is the right + place. config.h should never have direct includes anyway. + +2012-03-14 Hans de Goede <hdegoede@redhat.com> + + buildsys: Disable some warnings + Mostly so that they don't turn into errors when building from source: + -Wno-missing-field-initializers: + Because this has to be close to the most stupid warning gcc has ever produced + -Wno-deprecated-declarations + Because we use some deprecated functions to avoid #ifdef hell while maintaining + compat with older gtk / glib versions + + usbredir: Check for existing usb channels after libusb init + Currently trying to view a usbredir enabled vm from virt-manager causes + virt-manager to crash. This crash is caused by the following happening: + + -virt-manager sets up the session, including connecting all the channels + -a spice-gtk internal code path calls spice_usb_device_manager_get() + -spice_usb_device_manager_get calls channel_new on all already connected + usb channels + -channel_new does: + spice_usbredir_channel_set_context(SPICE_USBREDIR_CHANNEL(channel), + self->priv->context); + -But self->priv->context has not been set yet (so is NULL) -> segfault! + + This patch fixes this by moving the iterating over already connected + usb channels to after the setting of self->priv->context. Note this means + that the channels will no longer get checked when there is no USB_REDIR + support. That is not a problem since spice_usb_device_manager_initable_init + will return FALSE in that case anyways. + +2012-03-14 Marc-André Lureau <marcandre.lureau@redhat.com> + + Use GTK_DISABLE_DEPRECATED to avoid inclusion of problematic headers + /usr/i686-w64-mingw32/sys-root/mingw/include/gtk-2.0/gtk/gtkitemfactory.h:47:1: error: function declaration isn't a prototype [-Werror=strict-prototypes] + + Fix 'libintl_printf' is an unrecognized format function + ../common/lz.h:18:5: error: 'libintl_printf' is an unrecognized format function type [-Werror=format] + + Remove deprecation warnings + +2012-03-14 Daniel P. Berrange <berrange@redhat.com> + + Disable -Wwrite-strings for Python binding + The code generator for the python binding generates code which + throws away const-ness on strings. Disable the -Wwrite-strings + warning to avoid failing on this auto-generated code. + +2012-03-13 Daniel P. Berrange <berrange@redhat.com> + + Replace %02hhx with %02x in UUID format + Use of 'hh' in the UUID format string is not required. Furthermore + it causes errors on Mingw32, where the 'hh' modifier is not supported + + Import GNULIB's GCC warning macros + GNULIB has a helpful module 'manywarnings' which makes it easy + to turn on every single GCC warning. The general goal is that + every possible GCC warning should be enabled, except for certain + blacklisted warnings. + + This imports the GNULIB m4 macros, and updates configure.ac to + use this new capability. As & when new GCC warnings are created, + the 'manywarnings.m4' can be refreshed from upstream GNULIB + + * m4/manywarnings.m4, m4/warnings.m4: GNULIB warning macros + * configure.ac: Remove custom compiler warning checks + * m4/spice-compile-warnings.m4: Decide what GCC warnings to enable + + Avoid 'goto' jumping over variable initialization + When a goto statement jumps over a variable declaration with an + initializer, the state of that variable is undefined. Move the + declaration further up, so that the goto doesn't jump over it. + This lets the compiler then warn, if the goto jump results in + use of undefined values. + + Fix no-arg functions declared () to use (void) + * common/quic.h, common/rop3.h, common/sw_canvas.h: s/()/(void)/ + + Add missing includes & make some functions static + A number of functions were used without prior declaration. In + some cases this was due to missing include files. In other cases + the functions should have just been static. + + Ideally this would allow -Wmissing-declarations to be enabled, but + the files generated by spice_codegen.py will still trip up on this. + + Ensure all no-args methods are declared (void) not () + * common/quic.c, common/rop3.c, common/sw_canvas.c, + gtk/spice-client-glib-usb-acl-helper.c: s/()/(void)/ + + Add printf format annotations to all '...' functions + To allow the compile to detect incorrect printf formats, any + var-args function should have a format annotation + + * common/macros.h: Helper to define ATTR_PRINTF for code + which can't depend on glib + * common/canvas_base.c, common/lz.h, common/macros.h: Annotate + some var-args methods + + Replace duplicated header declarations + The usb-helper-acl.h header file duplicated some declarations + already present in usb-device-manager.h + + The channel-display.c file declared the object init function + which is already done by the GObject helper macros + + * gtk/channel-display.c: Remove duplicate decl of init function + * gtk/usb-acl-helper.h: Remove duplicate decls + + Remove arithmetic on void* pointers + Arithmetic on void * pointers is undefined by the C standard. + Convert the one case of this to use guint8 instead. + + * gtk/channel-main.c: s/void */guint8 */ + + Fix some integer range checks which always evaluate false + There are some integer range checks which always evaluate false + due to use of unsigned integer types. One of these would prevent + detection of encoding errors from celt. The others are simply + no-ops. + + * gtk/channel-record.c: Make 'frame_size' signed to allow detection + of celt encoding errors + * gtk/spicy.c: nkeys is an unsigned type, so checks for nkeys < 0 are bogus + * common/pixman_utils.c: SpiceROP is an enum & thus unsigned + + Avoid warnings about empty conditional statement bodies + Add extra {} braces around if/else statements which only + call SPICE_DEBUG to avoid: + + ../common/ssl_verify.c: In function 'verify_pubkey': + ../common/ssl_verify.c:87:50: warning: suggest braces around empty body in an 'else' statement [-Wempty-body] + ../common/ssl_verify.c: In function 'verify_hostname': + ../common/ssl_verify.c:254:53: warning: suggest braces around empty body in an 'if' statement [-Wempty-body] + ../common/ssl_verify.c: In function 'verify_subject': + ../common/ssl_verify.c:381:41: warning: suggest braces around empty body in an 'else' statement [-Wempty-body] + + Fix deprecation warning handling + Various methods are deprecated by using the G_GNUC_DEPRECATED_FOR + macro. Unfortunately this macro was placed in the .c file impl, + instead of the .h file decl. Thus applications building against + SPICE-GTK would never see the deprecation warnings. At the same + time, building SPICE-GTK itself would trigger some of the warnings + preventing use of -Wdeprecated-declarations to detect use of + deprecated GTK functions. + + The fix is in multiple parts + + * Replace calls to G_GNUC_DEPRECATED_FOR with SPICE_DEPRECATED_FOR + * Move macros from .c to .h files + * Turn SPICE_DEPRECATED_FOR into a no-op if SPICE_NO_DEPRECATED + is defined + * Define SPICE_NO_DEPRECATED when building + + Fix old style declaration where 'inline' came after return type + Fix a case of 'static int inline' to be 'static inline int' + + Fix const-correctness of functions & add explicit casts + Some functions should be declared to take const char * instead + of plain char *. In other places we intentionally cast away + const-ness, so we should add explicit casts to stop compiler + warnings + + Remove non-existant include directories from CFLAGS + + Don't delete gtk-doc.make in distclean + gtk-doc.make is created by autogen.sh, therefore it should + not be deleted in distclean, only maintainerclean + +2012-03-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + Release v0.11 + + Update since annotation for some session properties + +2012-03-08 Hans de Goede <hdegoede@redhat.com> + + channel-usbredir: Handle some more usbredirhost_read_guest_data errors + +2012-03-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + Do not warn when starting spicy if usbredir is disabled + + sasl: sasl authentication failure results in disconnection + When SASL auth failure happen, the Spice server disconnects the + client. Sadly, this is not easily distinguishable from an IO error. + However, since it happens during authentication phase it is better to + error out an authentication error. + + sasl: lower visibility of normal debug message + Those two g_critical() can happen when collecting credentials for the + first time. It is not something to be warned about, but merely useful + for debugging + + build: move @SPICE_GLIB_REQUIRES@ to Requires.private + The libraries listed in Requires aren't needed during build time, they + are library depedencies. And since this is only needed if linking + statically, we can safely move them to Requires.private. + + Succesfully tested change with compilation against virt-viewer. + + Later, this will also help fixing bug rhbz #799112. + +2012-03-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix semi-seamless migration handling + SPICE_MSGC_MAIN_MIGRATE_END was dropped because the main channel was + xmit_queue_blocked. When we swap the channels, we should also swap + xmit_queue. + +2012-03-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + Warn if a message is dropped (before connection or after reset) + Since c2ba62666beaee526e1b4288f9bd66976ce780ef messages can be ignored + when a channel is reset. A warning can help explain why some messages + are dropped. + + Support name & uuid + Allows a client to identify the server it is connected to. + +2012-02-29 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add a spice-controller-dump testing tool + By default, start a controller listener. + If ran with --menu, start a foreign-menu listener. + + Add controller foreign menu support + + Fix a few warnings on windows build + + Allow open_fd() to be called with -1 + In this case, a valid fd will be requested via the + SpiceChannel::open-fd signal. + +2012-02-24 Hans de Goede <hdegoede@redhat.com> + + buildsys: Don't link glib-compat.o into libspice-client-gtk.so + glib-compat.c was added to SPICE_GTK_SOURCES_COMMON since with the + new SpiceUsbDeviceWidget libspice-client-gtk now also uses G_TYPE_ERROR + and when compiling with an older glib this gets defined in glib-compat.o + + However doing this turns out to be a very BAD idea, since having + glib-compat.o linked into 2 different libraries, each defining there + own private spice_error_get_type, leads to the "GError" type getting + registered twice with glib, which it does not like. + + So instead of linking glib-compat into 2 different libraries, put it only + in libspice-client-glib and export spice_error_get_type from + libspice-client-glib (this is ofcourse intended for libspice-client-gtk + private use only). + + Fix building with policykit < 0.101 + +2012-02-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + Release v0.10 + + use :glz-window-size not :glz_window_size + + build: fix build with recent mingw64 + Christophe did similar patches for common/ directory in spice. Some + day, we should try to sync and move common/ to a spice-common + project... + +2012-02-22 Hans de Goede <hdegoede@redhat.com> + + usbredir: Add awareness of host/guest side filtering + + usbredir: Add a spice_usb_device_manager_can_redirect_device function + Add a spice_usb_device_manager_can_redirect_device function and use this + in SpiceUsbDeviceWidget to check if redirection is available. + + usb-device-widget: Use an info_bar for error messages + And in general gnome-hig-ify usb-device-widget: + * Use spacing instead of padding so that there is no padding at the + outside/border of the widget, allowing the user to control the border size. + * Use multiple of 6 as spacing / indentation values + * Show the label left justified and bold, show the checkboxes (and the info + bar) 12 pixels indented from the label + + configure: Fix "USB redirection support" summary on --disable-usbredir + When running "./configure --disable-usbredir" the + "USB redirection support" line in the summary at the end of ./configure + would be empty after "support" instead of ending with yes or no. + + usbredir: Treat the user cancelling the policykit dialog as a cancel + Rather then treating it as any other error. This avoids showing an error + dialog after the user pressed cancel in the policykit dialog. + + usbredir: Add device rejected errors + +2012-02-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + RFC: Use spice protocol as a submodule + Spice protocol contains only headers. We would like to be able to use + a protocol update without having to wait for the release, a git + submodule works well for this purpose. + +2012-02-20 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix make distcheck + +2012-02-20 Hans de Goede <hdegoede@redhat.com> + + usbredir: Shrink the usb device selection dialog when devices are unplugged + + usbredir: make channel lifetime equal to session lifetime + + usbutil: Add support for getting strings from usb.ids + Unfortunately not all device makers go to the "trouble" of adding device + identification strings to a device's descriptors. This patch makes spice-gtk + translate vid/pid into strings if the device lacks the strings. + + usbutil: Add a spice_usb_util_get_device_strings helper function + + usb: Move various helper functions into usbutil.[c,h] + +2012-02-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add controller ENABLE_SMARTCARD message + +2012-02-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + widget: fix mouse wrapping failing when the window is outside + Use a anchor mouse position after every move, similar to spicec to + avoid reaching transparent border on the screen. + + We try to move to the center of the screen, but + gdk_display_warp_pointer () will move the cursor within the grabbed + window (so it still receives mouse events even on Windows) + + Tested with Linux and Windows clients. + + Fixes bug: https://bugs.freedesktop.org/show_bug.cgi?id=45595 + +2012-02-13 Nicolas Prochazka <prochazka.nicolas@gmail.com> + + Set keepalive on channel socket + Without keepalive on each connection(channel), channel is destroyed + after ip_conntrack_tcp_timeout_established timeout. + + https://bugs.freedesktop.org/show_bug.cgi?id=45899 + +2012-02-12 Marc-André Lureau <marcandre.lureau@redhat.com> + + Use an openssl BIO stream using GSocket + Until now, the BIO object used by openssl to read & write was using + the socket fd directly. But the mainloop integration is done with + GSocket. + + On Windows, the read/write events are cleared after + g_socket_send()/receive() with private function + _win32_unset_event_mask. If the glib functions aren't cleared, glib + source will keep notifying of data available in or out. On Windows, + this causes a busy loop when doing SSL_read() for example (glib + POLL_IN data condition is reached and SSL_read() return needs data). + + Instead, openssl should read/write using GSocket methods. + +2012-02-09 Daniel P. Berrange <berrange@redhat.com> + + Don't warn if setsockopt(TCP_NDELAY) fails with errno==ENOTSUP + If connecting to a UNIX domain socket, it is expected that the + setsockopt(TCP_NDELAY) call will fail with errno=ENOTSUP, so don't + issue a warning in that case + +2012-02-08 Christophe Fergeau <cfergeau@redhat.com> + + Link with usbredirparser + spice-gtk uses usbredirfilter_string_to_rules which is defined + in usbredirparser but does not link with it. This causes link errors + on some distributions. Fixes fdo bug #45761. + +2012-02-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + Lower or silence some harmless debug messages + +2012-02-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + widget: allow defining a zoom-level + Add a "zoom-level" property. Maintain the given scaling ratio when + scaling is enabled. + + If scaling is disabled, this property is ignored. + + For example at 50%, this allows to fit a 640x480 desktop in a 320x240 + widget and when resizing it to 640x512 to have a 1280x1024 desktop. + + (this feature is required by virt-viewer) + + widget: factor out update_size_request() and scaling_updated() + Factor out and simplify a little the code to allow easier addition of + zoom-level property. + + The "set_display" parameter for recalc_geometry() seems to be useless, + since the code was apparently trying to set the guest to the given + d->width and d->height, but reseting it to the current value, which + cancel the effect. + + We should fix the problem of setting the guest resolution at + display-init time in a follow-up patch since it probably never worked + with spice-gtk. + +2012-01-31 Marc-André Lureau <marcandre.lureau@redhat.com> + + Report the scaling is 1.0 if the widget isn't realized yet + To avoid a few warnings in some corner cases. + + Do not grab/release the clipboard on guest without clipboard support + Add an agent capability check before calling those functions from + gtk-session. Avoid extra warnings. + +2012-01-31 Hans de Goede <hdegoede@redhat.com> + + Release 0.9 + + Add a USB device selection widget + This patch adds a SpiceUsbDeviceWidget which apps can use to easily + add an UI to select USB devices to redirect (or unredirect). + + See spicy for an example usage. + +2012-01-30 Hans de Goede <hdegoede@redhat.com> + + usb-device-manager: Cleanup USB manufacturer and product strings + The strings returned by devices sometimes can benefit from some clean-up. + +2012-01-28 Hans de Goede <hdegoede@redhat.com> + + spice-client-glib-usb-acl-helper: Fix mention of Lesser in license header + + spice-client-glib-usb-acl-helper: ensure we set the acl on a chardev + Josh Bressers has been so kind to review the usb-acl-helper for possible + security issues. One of his recomendations was to ensure that the file + we're setting the acl on is a chardev. + + spice-client-glib-usb-acl-helper: Fix memleak + Not really important given the short livedness of the process, but + still should be fixed. + + configure: Add an option for building the acl helper as PIE + Josh Bressers has been so kind to review the usb-acl-helper for possible + security issues. One of his recomendations was to harden the usb-acl-helper + by building it as a Position Independent Executable. + + configure.ac: s/x"$have_foo"/"x$have_foo"/ + configure.ac was using 2 slightly different styles for have_foo tests: + if test x"$have_foo" = "xyes"; then + and: + if test "x$have_foo" = "xyes"; then + + Switch to the latter style everywhere for consistency. + + configure.ac: Cleanup policykit checks + * No need to set AM_CONDITIONAL WITH_POLKIT from the enable_usbredir tests, it + get sets from the enable_polkit tests in all paths + * Improve the help text: mention auto as option, policykit -> PolicyKit, + not yes but auto is the default + * Warn when building with usbredir support but not building the acl helper + +2012-01-24 Christophe Fergeau <cfergeau@redhat.com> + + Add check for Perl::Text::CSV + This check is only added to configure.ac contrary to the pyparsing + patch. + + Add check for pyparsing + Check both in configure.ac (after checking if we need to rebuild + the marshalling files) and in the python script using pyparsing + (for people modifying .proto files in tarballs) + + Use PKG_CHECK_EXISTS for g-i has_symbol_prefix check + GOBJECT_INTROSPECTION_CHECK will alread test for the presence of + gobject-introspection. The PKG_CHECK_MODULES(GOBJECT_INTROSPECTION) + call only needs to set the has_symbol_prefix variable, so we can + use PKG_CHECK_EXISTS here, and let GOBJECT_INTROSPECTION_CHECK do + the rest of the work. + + Autodetect usbredir and PolicyKit by default + Currently, usb redirection and policykit are enabled by default, + and configure will error out if the required dependencies cannot + be found. This commit changes the default behaviour, by default + usb redirection/policykit support is automatically enabled/disabled + depending on the availability of the needed dependencies. Passing + --enable-usbredir will error out if the dependencies for usb + redirection cannot be found, ditto for policykit. This should make + things nicer for people running configure or autogen.sh with no + argument. + +2012-01-24 Yonit Halperin <yhalperi@redhat.com> + + Add command line options for setting the cache size and the glz window size + This options will help us tune and find the optimal values. + + Change the setting of the images cache size and the glz window size + Set the default sizes to be the same as in the old linux spice client. + cache_size=20M pixels (instead of 32M), window_size=8M pixels for a 64MB + dev ram (instead of 16M pixels). + +2012-01-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix vapigen error and warnings + Thanks to Jeremy Bicha for the bug report and testing solution. + + https://bugs.freedesktop.org/show_bug.cgi?id=45154 + +2012-01-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + controller: use a controller listener abstraction + Add a wrapper file for named pipe and socket listener, so we can release + tarball with code compatible with windows and unix. + + build: use AM_GLIB_GNU_GETTEXT + For some unknown reason, this set DATADIRNAME='share' on Windows, + which is what is expected. + + Although some people say only IT_PROG_INTLTOOL is necessary, it gets + the path wrong in this case too. + +2012-01-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk-session: weak reference the session for clipboard cb + It seems Gtk is lacking a way to cancel a gtk_clipboard_request_*(). + + Although it seems like gtk_selection_remove_all() would solve that + problem, it will have nasty effect of destroying other pending + requests from others.. + + Let's make use of an extra weak reference object that will be nulled + when the session is destroyed. + + This should help solving the follwing bug: + https://bugzilla.redhat.com/show_bug.cgi?id=743773 + + gtk-session: ignore destroy of outdated main channel + This solves clipboard sharing not working with a password protected + server, since new main channel are created for each connection + attempt. + +2012-01-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: allow out-of-tree building of python bindings + +2012-01-17 Hans de Goede <hdegoede@redhat.com> + + spice-channel: Allow calling spice_msg_out_send from any context + spice_msg_out can be not only called from system context and usb event + handling thread context, but also from co-routine context. Calling from + co-routine context happens when a response gets send synchronously from + the handle_msg handler for a certain received packet. This happens with + certain usbredir commands. + + This triggers the following assert in the coroutine code: + "GSpice-CRITICAL **: g_coroutine_wakeup: assertion `coroutine != + g_coroutine_self()' failed" + + This patch fixes this by making spice_msg_out_send callable from any + context and at the same time changing the code to not do unnecessary + wakeups. + +2012-01-16 Hans de Goede <hdegoede@redhat.com> + + gtk/display: Get rid of old FSF address in copyright headers + rpmlint pointed this out while I was checking the new spice-gtk-0.8 package + for Fedora. + +2012-01-16 Christophe Fergeau <cfergeau@redhat.com> + + Handle spice_audio_new failures + spice_audio_new can return a NULL pointer when there's a failure + during the initialization of the audio system. When this happens, + we shouldn't keep initializing the spice audio channel as if nothing + happened, but just stop the connection. + This can be tested by forcing the "self" variable to NULL in + spice_audio_new + This should fix https://bugzilla.redhat.com/show_bug.cgi?id=772118 + +2012-01-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + Release 0.8 + + Generate ChangeLog and ship it in the tarball + + Send grab-key signal even in mouse client mode + +2012-01-15 Hans de Goede <hdegoede@redhat.com> + + usbredir: Add support for filtering out devices from auto-redirection + Note this patch adds a default filter filtering out HID devices, since + redirecting ie a mouse plugged into a laptop is usually not what the user + wants. Also sometimes usb keyboards/mice may experience a glitch causing + them to temporarily drop of the bus. If this happens when the spice-client + has focussed it used to redirect them to the vm when they re-appeared, + not good! + +2012-01-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix compilation on mingw/windows + + Warn if windows keyboard hook failed + + Don't release images after the tail gap + This fix a hang on an image lookup that has already been remved. It + only happens in multihead, when stressing a bit the displays. + + The decoder assumed that the last added images is the tail of the + window. However, there are "gaps" in the window that will be filled by + other channels. Instead of taking the last added image as the current + up to date tail, let's take the reference to the last image before the + first gap as the up to date tail, and release from there. + + The spicec code does things differently, perhaps it needs slightly + less memory at the cost of added complexity by maintaining list of + missing images and much more conditions/synchronization. + + Grab focus before grabing keyboard + Make sure the display has the focus before grabing the keyboard for + the application. + +2012-01-12 Marc-André Lureau <marcandre.lureau@redhat.com> + + wait for cached images that haven't been added to the cache yet + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Log if condition wait got cancelled + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Make g_coroutine_condition_wait() cancellable + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Remove the non-interruptible version g_io_wait() + Use the common g_coroutine_socket_wait() + + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Create a GCoroutine, get rid of wait_queue + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Hide g_condition_wait_source, use GLib style convention + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Lower connection error from warning to debug, it's normal to fail + We try several connections, so it's normal to fail for some. + No need to warn. + + https://bugs.freedesktop.org/show_bug.cgi?id=44570 + + Lower our gtk+ requirement to 2.18, as we claim + Needed to build on RHEL6 + + Lower polkit requirement to 0.96 + + Lower our glib requirement to 2.22, as we claim + Required to build on RHEL, even upcoming 6.3 + +2012-01-11 Yonit Halperin <yhalperi@redhat.com> + + migration: swap serials and mini header support when swapping peers. + + Add support for SPICE_COMMON_CAP_MINI_HEADER + Don't send/receive serial and sub_list when the server supports the + above cap. + +2012-01-10 Yonit Halperin <yhalperi@redhat.com> + + spice-channel: support SPICE_MSG_LIST + + configure: spice-protocol >= 0.10.1 (support mini header) + +2012-01-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + Wait for channels before invalidating images + https://bugs.freedesktop.org/show_bug.cgi?id=44179 + + Implement SPICE_MSG_WAIT_FOR_CHANNELS + https://bugs.freedesktop.org/show_bug.cgi?id=44179 + +2012-01-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + add optional format string to spice_usb_device_get_description() + +2012-01-07 Marc-André Lureau <marcandre.lureau@gmail.com> + + build: oops, fix previous commit + +2012-01-06 Marc-André Lureau <marcandre.lureau@gmail.com> + + build: fix compilation with --disable-usbredir + +2012-01-05 Alon Levy <alevy@redhat.com> + + spice-session: support uri with colon + With this patch if you use: + spice://<host>:<port> + + it will be treated the same as: + spice://<host>?port=<port> + + You will also get a warning for the following double port definitions: + spice://<host>:<port1>?port=<port2> + spice://<host>:<port1>:<port2> + + (similar to the double key warnings introduced in the previous commits) + + spice-session/spice_uri_parse: fail if a key is seen twice + +2012-01-04 Hans de Goede <hdegoede@redhat.com> + + Makefile: Ensure the acl helper is installed before making it suid root + On my system when running make install, after installing the libraries it + first executes install-binPROGRAMS: + + /bin/sh ../libtool --mode=install /usr/bin/install -c spicy snappy spicy-st + libtool: install: /usr/bin/install -c .libs/spicy /usr/bin/spicy + libtool: install: /usr/bin/install -c .libs/snappy /usr/bin/snappy + libtool: install: /usr/bin/install -c .libs/spicy-stats /usr/bin/spicy-stats + + Then the install-exec-hook: + + make install-exec-hook + make[6]: Entering directory `/home/hans/projects/spice/spice-gtk/gtk' + chown root /usr/bin//spice-client-glib-usb-acl-helper + chmod u+s /usr/bin//spice-client-glib-usb-acl-helper + + And only then does it install the actual helper by executing + install-aclPROGRAMS: + + /bin/sh ../libtool --mode=install /usr/bin/install -c spice-client-glib-usb + libtool: install: /usr/bin/install -c spice-client-glib-usb-acl-helper /usr/bin + + Which means that the install-exec-hook runs too early, either there is no + spice-client-glib-usb-acl-helper for it to make suid root, or if there is it + will later get overwritten and its rights will get reset. + + The problem is that install-fooPROGRAMS gets run as part of install-data, + not install-exec. So we can fix this by changing the code to make the helper + suid root run from install-data-hook. + + usbredir: Don't directly use g_mutex_foo() + In glib <= 2.30 g_mutex_foo() are macro's so dereferencing them directly + does not work. + +2012-01-03 Hans de Goede <hdegoede@redhat.com> + + usbredir: Don't call spice_usbredir_channel_disconnect on channel reset + channel_reset gets called from spice_channel_disconnect, and + spice_usbredir_channel_disconnect calls spice_channel_disconnect + (so as to disconnect the channel when a usb device gets disconnected). + + So calling spice_usbredir_channel_disconnect from channel_reset leads to + undesirable recursion. More over calling spice_usbredir_channel_disconnect + disconnects / closes both the channel and *the usb device* and closing the + usb device on migration is not what we want. + + Note that currently migration of usbredir channels does not work, and this + patch does not fix this, but it does fix a regression when disconnecting + usb devices normally (by unplugging them for example). + + usbredir: Give devices a user friendly description + Before this patch devices were described like this to the user: + USB device at 2-14 + After this patch the description is: + SanDisk Cruzer Blade [0781:5567] at 2-14 + + usbredir: Drop our embeddied GUsb copy + No that we no longer use GUsbSource we're hardly using any code from GUsb, + so drop our embeddied GUsb copy and do the last few things (device + enumeration through gudev) ourselves. + + usbredir: Remove spice_usb_device_manager_get main_context argument + Now that we no longer use a GUsbSource this is no longer needed. + + Note this is a change to our public API, but that is ok since we have not + yet done an official release with usbredir support. + + usbredir: Handle usb events from a thread + This solves various latency issues with USB handling. + + usbredir: Add locking callbacks for libusbredirhost + This is a preparation patch for handling usb packet completion in a + separate thread. + +2011-12-22 Hans de Goede <hdegoede@redhat.com> + + usbredir: Create USB event source on demand + This is a preparation patch for handling usb packet completion in a + separate thread. + + usbredir: Use new libusbredirhost write flush callback + The new (in usbredir-0.3.2) usbredirhost_open_full() + function allows us to be notified whenever usb packets completing + result in data to be send to the host. This removes the need for using + g_usb_source_set_callback and seeing if there is data to write on + any of the usb channels each time some usb event happens. + + This also bumps the minimum needed libusbredirhost version to 0.3.2 + + usbredir: USB channels can not be read only + A usbredir channel must always be bi-directional. spice-server + allows only one client to connect even when in multi-client mode. Since + usually there are multiple usb channels available, it is allowed for one client + to use one channel, while another client uses another usb channel. + + usbredir: Stop setting private data explictly to NULL on init + This is not necessary and as we get more private data it becomes + unyieldly. + + spice-channel: Allow spice_msg_out_send to be called from multiple threads + This is a preparation patch for handling usb packet completion in a + separate thread. + + spice-channel: setsockopt TCP_NODELAY + spicec does this for all channels, and it seems like a good idea to do the + same in spice-gtk. + +2011-12-22 Christophe Fergeau <cfergeau@redhat.com> + + Disable vala bindings unless --enable-vala is used + Currently, building vala bindings from a tarball is broken because + spice-client-glib-2.0.deps is missing from the tarball. This commit + adds it to EXTRA_DIST and also makes sure the vala bindings don't + get built/installed unless --enable-vala has been passed to configure. + This means vala must be installed to build the vala bindings from a + tarball. Fixes fdo bug #44000. + + Revert previous vala-related commits + They were work in progress and not meant to be committed, apologies + for the noise :-/ + + Only install vala bindings when using --enable-vala + + More distcheck fixes + +2011-12-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: ship vala files & fix make distcheck + Disable usbredir, since it wants to install file in /. + + Disable vala for distcheck for 2 reasons: not needed after dist and + binding build issue. + + Ship with spice-gtk-3.0 vala bindings + + https://bugs.freedesktop.org/show_bug.cgi?id=44000 + +2011-12-22 Christophe Fergeau <cfergeau@redhat.com> + + Make path to the USB ACL helper configurable + It's currently installed in $bindir, but this patch makes it possible + for distros like fedora to install it in $libexecdir/spice/ + +2011-12-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: remove unused common/win/my_getopt + +2011-12-22 Jani Välimaa <wally@mageia.org> + + build: string format fix + https://bugs.freedesktop.org/show_bug.cgi?id=44019 + +2011-12-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: depends on spice-protocol 0.9.1 + + Support semi-seamless migration + Yonit Halperin described the flow, that I followed: + + (1) when client_migrate_info is called SPICE_MSG_MAIN_MIGRATE_BEGIN is + sent to the client. + + Then, the client should link to the target server (SpiceLinkMess), + i.e., connect all the channels, but it shouldn't poll from the target, + only from the source. You can refer to RedClient::Migrate class. The + connection id in the link message should be the id of the connection + to the source server. + + (2) The client sends to the source server + SPICE_MSGC_MAIN_MIGRATE_(CONNECTED|CONNECT_ERROR) + + (3) When migration completes SPICE_MSG_MAIN_MIGRATE_(END|CANCEL) is + sent to the client. + + (3.1) In case of SPICE_MSG_MAIN_MIGRATE_CANCEL, the client closes the + connections to the target. + + (3.2) In case of SPICE_MSG_MAIN_MIGRATE_END, the client should reset + all the data that is related to the connection to the source and + complete the transition to the target server (without sending + ATTACH_CHANNELS, and without guest display initialization via agent). + + Then, the client sends SPICE_MSG_MAIN_MIGRATE_END to the target. + + main: Handle semi-seamless MIGRATION_BEGIN + + display: try to reuse exisiting primary surface + + Add channel_reset method + This new private method is to reset the channel to its initial state, + used by semi-seamless migration + + gio-coroutine: add a few more run-time checks + + Update protocol and messages for semi-seamless migration + +2011-12-19 Marc-André Lureau <marcandre.lureau@gmail.com> + + windows: initialize co->ret to not randomly release fiber + +2011-12-18 Frédéric Péters <fpeters@0d.be> + + add explicit links against libraries that are directly used + +2011-12-16 Hans de Goede <hdegoede@redhat.com> + + spice-channel: cleanup, remove spice_channel_send_msg() + There are only 2 callers, both of which want it to do a different thing, + making the callers do this directly allows us to remove + spice_channel_send_msg(); and gets rid of the weirdness where we've a + function which can be called in both co-routine and system context. + + spice-channel: Move read only check to spice_channel_write_msg() + This is a preparation patch for removing spice_channel_send_msg(). + + Note that this means that buffered writes won't get checked until they are + actually send by the co-routine. + + spice-channel: Move setting of header->size to spice_channel_write_msg() + Just a small cleanup patch. + + spice-channel: replace the xmit buf by a queue of SpiceOutMsg-s + This has a number of advantages: + -It significantly simplifies the code + -It avoids memcpy-ing all the write data one more time + -It avoids malloc / realloc / free of the xmit buffer + (this gets replaced by gslice alloc / free for the queue elements) + + Make sure spice_channel_iterate_write() always flushes *all* pending writes + This patch changes 1 line, and fixes 2 bugs in this one line: + 1) We keep the xmit_buffer around for reuse (re-filling) later, so checking + if we've a xmit_buffer to determine wether we should do a write is wrong, + instead we should check if the xmit_buffer has data in it. + 2) If the write blocks, and we switch to another co-routine context, this + context may queue more writes, we check for this and throw away the + buffer we've been consuming when this happens, since the other context + will then have allocated a new buffer. But when this happens, we do *not* + consume the new buffer. So the queued data will not get transmitted + until the co-routine gets woken up by either another write, or by + receiving data to read. + This patch fixes this by changing the if to a while. + + Note that the code in question gets completely removed by the next patch in + this series. As I noticed this while rewriting the code in question, still + I decided to do a separate patch to fix this to: + 1) Document this issue in the old code + 2) Otherwise the move from the if to the while will happen in the new code + which may confuse readers of that patch. + + spice_msg_out[_send_internal]: Take ownership of the passed SpiceMsgOut + All callers of spice_msg_out[_send_internal] unref the message immediately + after calling spice_msg_out[_send_internal]. This patch changes the + semantics so that spice_msg_out[_send_internal] takes ownership and it + is responsible for unref-ing the passed in SpiceMsgOut. + + This is a preparation patch for changing the buffered write code + to use a queue of SpiceMsgOut-s, rather then memcpy the message contents + into an intermediate buffer. + + channel-smartcard: unref in flight messages as soon as they are sent + This is a preparation patch for making spice_msg_out_send() take ownership + of the passed in msg. + +2011-12-15 Hans de Goede <hdegoede@redhat.com> + + smartcard_message_complete_in_flight cleanup error checking + smartcard_message_complete_in_flight should never get called if there + is no message in flight (priv->in_flight_message != NULL). + +2011-12-14 Hans de Goede <hdegoede@redhat.com> + + spice-channel: cleanup, get rid of wait_interruptible variable + The private wait_interruptible channel variable is not used anywhere, + except in one test, which is useless since it never gets set. + + Disable mouse accelleration when grabbing the mouse (in server mode) + Otherwise accel will be applied twice, once by the client and then once + more by the guest. Unfortunately there seems to be no gdk / gtk API for this + so this patch uses direct libX11 calls. + +2011-12-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + windows: fix broken left shift + On Windows, the received key when pressing left shift is VK_SHIFT 0x10 + + Wrap in window, because windows doens't receive mouse events outside it + + windows: clip pointer when grabbed, so it stays inside widget + +2011-12-12 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix crash on mouse server mode grab with gtk2 + With gtk3 gdk_cursor_unref = g_object_unref. But not with older + version. Let's be consitent with the rest of the code and use + cursor_unref(). + + build: add missing smartcard manager in python binding + Probably broken since the manually edited defs files have been removed + +2011-12-10 Hans de Goede <hdegoede@redhat.com> + + spice-widget: rename mouse_update to update_mouse_mode. + We already have update_mouse_pointer and update_mouse_grab, so having + a mouse_update function without specifying what "part" of the mouse handling + it exactly updates is confusing, rename it to update_mouse_mode to reflect + what it does and to match the other names. + + spice-widget: cleanup mouse handling. + Some background on this patch, we currently behave + as follows in server mouse mode: + + 1) When spicy first connects, a frozen guest cursor is shown + (no mouse events are send to the guest) and the client cursor + is set to the standard right pointer, + + 2) When one clicks on / inside the spice-widget, the mouse is + grabbed, the client cursor is hidden and the guest pointer + becomes alive (gets events). + + 3) On ungrab we move back to state 1) + + Which is fine, but the code implementing it is somewhat convoluted. + We have update_mouse_pointer(), which does more then just update the mouse + pointer, it also calls try_mouse_grab(), and we've update_mouse_grab(), + which calls update_mouse_pointer() rather then try_mouse_grab(). + + * I. lets look at what we currently have in update_mouse_pointer(): * + + case SPICE_MOUSE_MODE_SERVER: + if (!d->mouse_grab_active) { + if (gdk_window_get_cursor(window) != NULL) + gdk_window_set_cursor(window, NULL); + } else { + try_mouse_grab(display); + } + break; + + Now lets invert the test to make it more readable: + + case SPICE_MOUSE_MODE_SERVER: + if (d->mouse_grab_active) { + try_mouse_grab(display); + } else { + if (gdk_window_get_cursor(window) != NULL) + gdk_window_set_cursor(window, NULL); + } + break; + + Hmm, so if we're grabbing the mouse, we try to grab the mouse + -> does not make sense, esp not since try_mouse_grab() has: + + if (d->mouse_grab_active) + return; + + So we can drop the else block. + + But why the if? Well that would be because when we're grabbing + the windows should have a blank cursor. But where does that get set? + + The blank cursor gets set in do_pointer_grab(), by specifying a blank + cursor as the cursor to show as long as the grab is active. + + Since that cursor will be active as long as we're grabbing, so we can + drop the if (!d->mouse_grab_active) check as well. + + And with the mouse_grab_active check gone, we no longer need to call + update_mouse_pointer() from try_mouse_ungrab(). + + * II. lets look at update_mouse_grab() * + + So currently when the mouse should be grabbed according to the + mouse-grab and disable-inputs properties, update_mouse_grab() calls + update_mouse_pointer(), which as discussed above does nothing with the grab, + as the code path calling try_mouse_grab() is dead code. The right thing to do + would of course be to have update_mouse_grab() call try_mouse_grab() in this + case. + + But, that would mean that as soon as the property is changed the cursor will + get torn away from whereever it is and get grabbed, which may not always + be desirable. To fix this this patch also moves the mouse_have_pointer + and keyboard_have_focus checks from mouse_update() to try_mouse_grab() + + + foo + +2011-12-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix build issue because of double declaration + Patch based on Mageia, provided by Olav Vitters. + + https://bugzilla.freedesktop.org/show_bug.cgi?id=43457 + +2011-12-09 Michael Chudobiak <mjc@avtechpulse.com> + + use "connection" instead of "connexion" + +2011-12-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + Take the grab when mouse switching to client mode + Only when the widget has the focus and the pointer is over the widget + + Do not send ungrab key sequence to the server + + Don't leak cursor shape objects + + Refresh mouse shape/visibility when changing mouse mode + This fixes the dynamic mode changing when running/quitting the agent. + + Correctly hide client pointer (in server mode) + The hide cursor event happen when the widget is not yet + realized. Forcing realize may fail if the widget is not yet embedded + for example. Instead, let's update the cursor whenever there is a + draw(). + + v2: do not call gdk_window_set_cursor() with the same cursor + + Document the pointer ungrab for drag-n-drop in multihead + + Draw mouse with cairo in server mode + + Ignore the first mouse click when taking the grab + + Grab on the display too + Without this additional grab, the pointer grab was effective for the + whole application + + Add a get_blank_cursor() helper + + Use the border margin from recalc_geometry() + + Do not send pointer motion of 0x0 + + Warn with the connect connect socket error + + Fix controller with newer vala + +2011-12-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: vapi bindings only available if HAVE_INTROSPECTION + + controller: use SPICE_XPI_NAMEDPIPE first + +2011-12-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: do not clean spice-client-glib-2.0.deps + + build: fix linking with -Wl,--as-needed -Wl,--no-undefined etc.. + Mageia is using linker flags and miss symbols when linking. + The error can be reproduced with: + + make LDFLAGS="-Wl,--as-needed -Wl,--no-undefined -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags" + + Based on patch by Christophe Fergeau. + + https://bugs.freedesktop.org/show_bug.cgi?id=43416 + +2011-12-02 Hans de Goede <hdegoede@redhat.com> + + usb-device-manager: Don't g_warning on autoconnect failure + We already emit a signal for this, either the app using spice-client-glib + listens to this signals and does something with it, or it is not interested + in this happening, at which point logging a g_warning for it is not really + useful. + + spicy: Don't show an error dialog on a cancelled device open + If for example the user plugs in a new device, then gets the policykit agent + authentication dialog and then unplugs the device, spice-gtk will cancel + the acl-helper request, which in turn will dismiss the policykit agent + authentication dialog. Which is all a nice and smooth user experience, + except that when this happens spicy throws a dialog with an error + that the open was cancelled. Since a cancel usually is done deliberately + (such as on the user unpluging the device) no error dialog should be thrown + for it. + + channel-usbredir: Call the acl helper without first trying to open the device + Normally opening the USB device without first calling the helper will fail, + except when the process using spice-gtk is running as root. + + So the current code which first tries to open the USB device before calling + the helper is optimizing for an exception rather then for the default code + path. More over it also causes libusb to print the following errors to stderr: + libusb:error [op_open] libusb couldn't open USB device /dev/bus/usb/002/017: Permission denied. + libusb:error [op_open] libusb requires write access to USB device nodes. + + So this patch changes things to first call the helper and only then try + to open the device node. + + This patch also modifies the helper to not call policykit when called by + a root process, since the set_facl which it will do, if policykit says it + is ok, is a no-op for root anyways. Instead it directly returns a success + status without doing anything when called by a root process. + +2011-12-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + string formatting fixes + Patch based on Mageia, provided by Olav Vitters. + + https://bugs.freedesktop.org/show_bug.cgi?id=43456 + +2011-12-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + Move auto-connect logic in Audio base class + + Make UsbDeviceManager main-context a boxed property + +2011-11-26 Marc-André Lureau <marcandre.lureau@gmail.com> + + Fix get_type() with --disable-smartcard + It's quite a bad hack, but I can't think of anything really better + + Without this patch, g-ir-scanner introspection hangs with: + GLib-GObject-CRITICAL **: g_boxed_type_register_static: assertion `boxed_copy != NULL' failed + + GLib-CRITICAL **: g_once_init_leave: assertion `result != 0' failed + + GLib-GObject-WARNING **: gsignal.c:1585: parameter 1 of type `<invalid>' for sig + nal "SpiceSmartcardManager::reader_added" is not a value type + +2011-11-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + Do not send specific messages in read-only + + Check if msg are permitted to be sent in read-only + + Add read-only property on sessions + It is useful to have a way to prevent sending commands in read-only + sessions (think of multi-client) + + No clipboard sharing allowed in this case in gtk-session. + + Add disable-inputs on Spice widget + + cleanup: the try_grab() functions should take a SpiceDisplay + + Fix a few g-ir-scanner warnings + + Export spice_g_signal_connect_object + The helper needs to be accessible from spice-client-gtk too. + + Regenerate map-file correctly + We should use update-map-file instead of modifying it manually + +2011-11-21 Hans de Goede <hdegoede@redhat.com> + + Release our keyboard grab when we're going to invoke the usb acl helper + The usb acl helper asks policykit, which may want to interact with the + user through the policykit agent, which wants to grab the keyboard, if + we then have the keyboard grabbed, the agent says authentication has failed, + policykit rejects the helper opening up the acl and usbredir won't work. + + Unfortunately the only way to work around this is to temporarily release our + own keyboard grab, not pretty but as discussed on irc, this is the "best" + solution. + +2011-11-16 Hans de Goede <hdegoede@redhat.com> + + Add a suid root helper to open usb device nodes + spice-client needs to be able to open the device nodes under /dev/bus/usb + to be able to redirect a usb device to the guest. Normally opening these + nodes is only allowed by root. This patch adds a suid root helper which + asks policykit if it is ok to grant raw usb device access, and if policykit + says it is ok, opens up the acl so that the spice-client can open the device + node. + + As soon as spice-client closes the stdin of the helper, the helper removes + the extra rights. This ensures that the acl gets put back to normal even if + the spice client crashes. Normally the spice-client closes stdin directly + after opening the device node. + + channel-usbredir: Make spice_usbredir_channel_connect async + With the (upcoming) introduction of the usb device node acl helper, which + uses policykit, spice_usbredir_channel_connect() may take a long time as + it will be waiting for the helper, which will be waiting for policykit which + may be interacting with the user -> Make spice_usbredir_channel_connect() async + + Note that this patch only changes spice_usbredir_channel_connect's + API to use the standard GIO async API, it is not actually async after this + patch since it does not yet call the acl helper. + + usb-device-manager: Make spice_usb_device_manager_connect_device async + With the (upcoming) introduction of the usb device node acl helper, which + uses policykit, spice_usbredir_channel_connect() may take a long time as + it will be waiting for the helper, which will be waiting for policykit which + may be interacting with the user. So spice_usbredir_channel_connect() will + need to become async, and since spice_usb_device_manager_connect_device + calls spice_usbredir_channel_connect it thus also needs to become async. + + Note that this patch only changes spice_usb_device_manager_connect_device's + API to use the standard GIO async API, it is not actually async after this + patch since spice_usbredir_channel_connect is not yet async. + + channel-usbredir: Move usb device opening into a helper function + This is a preparation patch for adding the usb device node acl helper + + channel-usbredir: Do disconnect from dispose instead of from finalize + + channel-usbredir: Fixup and simplify #ifdef USE_USBREDIR handling + glib does not like it when objects have a private data size of 0, so don't + declare any private data when compiling without USE_USBREDIR set. + + Correct Since tag for SpiceSession:enable-usbredir: + This was introduced post 0.7, and given the major changes done in git + sofar the next release will be 0.8 rather then 0.7.1 + +2011-11-09 Christophe Fergeau <cfergeau@redhat.com> + + Use correct GLib macros + +2011-11-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + Mark deprecated props/signals/functions + + Remove g_object_{set,get}_data() usage + This is not really clean, as it may conflict with client usage + + Drop useless memset + Private data in GObject's is initialized to 0's upon constuction + + Use G_PARAM_CONSTRUCT for property initial value + +2011-11-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add missing include of spice-audio + + Add session enable-audio property + Create audio channels only if enable-audio is TRUE + + SpiceAudio stream name default to get_application_name() + + Add spice_audio_get() + We are going to deprecate spice_audio_new() + some day. There are a few know problems: + - SpiceAudio is an abstract class, + so it can't have a ctor + - SpiceAudio should be a singleton, + associated with the session lifetime + - SpiceSession should have a enable-audio property, + internal code should be able to access the audio object + + That way of getting the audio object is similar to the smartcard manager and usb manager. + +2011-11-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + Return NULL if taking screenshot fails + It can happen if the display is not yet ready. + This change just removes a couple of warnings. + + Fix package `SpiceClientGLib-2.0' not found + +2011-11-02 Tiziano Müller <tiziano.mueller@stepping-stone.ch> + + Correctly parse RFC-conform URIs separating the host and the arguments by a '/' + Little patch to make spice-gtk accept RFC-conform URLs of the form + "spice://host/?port=5901". + + I didn't add '/' to the list of the other characters to ignore (?;&) + by intention since an URL like spice://host/?port=5901/somotherstuff + should not be valid, resp. the password may contain '/' because the + string is already unescaped at that point. + + Unfortunately glib does not seem to have functions to 'explode' an URI + which would be really helpful. + + Cheers, + Tiziano + +2011-11-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk-session: add more checks + +2011-10-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add missing spice-gtk-session.h in spice-widget.h + +2011-10-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add vapi bindings generation + +2011-10-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + Fix missing dispose() chain-up + +2011-10-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + do not segfault if link message header size is set to 0 + https://bugs.freedesktop.org/show_bug.cgi?id=41988 + +2011-10-11 Marc-André Lureau <marcandre.lureau@redhat.com> + + Add SPICE_NOGRAB environment variable for debugging + + gtk: channel-event emit an enum + This doesn't break ABI, as int and enum are compatible at glib level. + + gtk: warn if argument is invalid instead of crash + +2011-10-10 Hans de Goede <hdegoede@redhat.com> + + Add spice-gtk-session-priv.h to make dist output + Brown paper bag bug number 2 wrt spice-gtk-session-priv.h, sorry about this. + + Add missing spice-gtk-session-priv.h file + This file was missing from the previous commit, my bad. + + Make auto-usbredir a session setting rather then a per display setting + + spicy: Stop using SpiceDisplay's deprecated clipboard methods + + SpiceDisplay: mark clipboard properties and functions as deprecated + The SpiceGtkSession ones should be used instead. + + SpiceDisplay: Don't set auto-clipboard on construction + The auto-clipboard setting now lives in the SpiceGtkSession, if that + was changed to FALSE (from the default of TRUE) and later a SpiceDisplay + was created for this session that would change it back to TRUE again because + it would set it to its default from its constructor. This patch fixes this. + + Remove auto-generated .gitignore files from git + Auto-generated files do not belong in git. Having these in git causes + changes to them accidentally ending up in other commits. + + Fix compilation of python bindings + This was broken by the addition of SpiceGtkSession. + +2011-10-07 Hans de Goede <hdegoede@redhat.com> + + decode-glz: Handle needing glz images before they have arrived + With multi monitor guests, it is possible for a glz-image to refer to + bits from another glz-image which has not arrived yet! This can happen + because each monitor has its own display channel, and thus its own socket, + but they share the glz dict. Thus things can arrive out of order, with a + glz-image on display 1 arriving before the glz-image on display 2 which it + refers too. + + This triggers the: + g_return_val_if_fail(w->images[slot]->hdr.id == id - dist, NULL); + + In glz_decoder_window_bits(), which is what caused me to debug this, once + the out order thing was clear, so was the fix. + If w->images[slot]->hdr.id == id - dist is not true, we need to wait for the + correct image to arrive. + + The out of order issue with multiple monitors can also trigger the + g_warn_if_reached() in glz_decoder_window_resize(), so remove that. + + SpiceDisplay: Pass on notify signal from GtkSession for GtkSession properties + Since some SpiceDisplay properties are now just a pass through to the + equivalent SpiceGtkSession property, we also need to pass on the notify + signal for these, so interested users can get notified of them changing. + + Use this in spicy to ensure that changes to SpiceGtkSession (and thus per + session rather then per window) properties get reflected in all windows for + a multimonitor guest. + + usb-device-manager: One instance per session instead of a singleton + Since usb device manager keeps track of which usb channels there are and + if they have usb devices attached there should be one usb-device-manager + instance per session, rather then one global singleton. + + Tying the usb-device-manager to the session also allows us to get rid of + spice_usb_device_manager_[un]register_channel and the need for SpiceDisplay + to call these. + +2011-10-06 Hans de Goede <hdegoede@redhat.com> + + SpiceDisplay: Add a constructor and construction properties + With SpiceDisplay now passing through auto-clipboard settings to + SpiceGtkSession, it needs to have its SpiceSession and SpiceGtkSession + private members initalized at construction time, as + spice_display_set_property() gets called at construction time. + + Currently its SpiceSession and SpiceGtkSession are NULL when that + happens leading to the g_object_set() calls in spice_display_set_property() + triggering g_return_if_fail statements inside glib and rightly complaining + loudly. + + This patch fixes this by making the SpiceSession and channel ID construction + properties and passing them to the g_object_new call in spice_display_new. + + Move clipboard handling to SpiceGtkSession + This fixes copy and paste with multi-monitor guests. There still is + one small issue left with this patch, changing the setting for auto-clipboard + in one spicy window, does not get reflected in the Options menu of the + other spicy windows. + + This can be fixed by listening to the notify signal, this also requires + SpiceDisplay to listen to property changes on its SpiceGtkSession and + then do a g_object_set on itself to update its own property (and also + emit its own notify signal. + + I'll write a separate patch for this. + + Add a SpiceGtkSession Class + This initial commit of the SpiceGtkSession Class only adds the empty + class and the 1:1 linkage to SpiceSession through 2 new private methods + added to SpiceSession: spice_session_{get|set}_gtk_session. + + The following commits will move things which are currently per SpiceDisplay, + but which really should be global, such as the clipboard, over to + SpiceGtkSession. + +2011-10-04 Hans de Goede <hdegoede@redhat.com> + + Fixup some headers so that they include headers the depend up on. + Otherwise they cannot be included unless other headers are included + first (and in the right order). + +2011-09-30 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: Add missing <package> and <c:include> in gir + This is required for source-level binding, such as Vala. + +2011-09-30 Hans de Goede <hdegoede@redhat.com> + + spice_codegen: Always write a channels entry for an ifdef-ed channel + Before this patch, if a channel is defined conditionally in spice.proto + (because it depends on external headers like the smartcard channel), + spice_codegen would write an entry to the channels array in + spice_get_*_channel_parser which would only take up a place in the array + if the ifdef condition is true, thus moving up all other intializers + one place when it is not true. This was causing issues (crashes) when building + spice-gtk with the combination of usbredir support enabled and smartcard + support disabled. + + This patch fixes this by adding #else { NULL, 0 }, to the generated code. + + Thanks to coolper chen <lixin.chen@saicocch.com> for reporting this! + +2011-09-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: move G_DEFINE_BOXED in glib-compat.h and fix build with old glib + + pulse: use spice_g_signal_connect_object + Disconnect all handlers when either emitter or observer is gone. + That should help https://bugzilla.redhat.com/show_bug.cgi?id=737202 + + util: add spice_g_signal_connect_object + This is a copy of telepathy-glib tp_g_signal_connect_object. + + That function allows to connect object's signals without + having to worry much about emitter/observer lifetime. + + It handles automatic disconnection for us, no need to track + all the handlers id. Nice! + +2011-09-02 Hans de Goede <hdegoede@redhat.com> + + gtk/Makefile.am: Better explicit deps fro autogenerated files + Auto-generated files need explicit deps on them to ensure things + are build in the right order when doing things like make -j200: + 1) We had an explicit deps on spice-marshal.h, but only for spice-channel.c, + but others need it to + 2) autogen.c files need autogen.h, note this is done in a separate make + statement, since the deps of the actual build rule are used during the + generation! + 3) Group all the autogen explicit deps together + + configure.ac: Update minimum required spice-protocol to 0.9.0 + This is needed for usbredir support. + + gtk/continuation.c: undef _FORTIFY_SOURCE earlier + We need to undef _FORTIFY_SOURCE before our first include, so as to + avoid the extra checks it does on longjmp which don't play well with + our coroutine stuff. + + gtk/controller/Makefile.am: Add explicit rules for autogenerated files + The autogenerated files are part of make dist, without these explicit + rules doing "./autogen.sh && make dist" on a clean git checkout + will fail because it wants them but does not know how to build them. + + gtk/Makefile.am: Remove a bunch of .c files from EXTRA_DIST + automake is smart enough to add _SOURCES files to make dist's result even + if there compilation is depending on an AM conditional, and we are already + depending on this for the smartcard / usb files, so lets depend on it for + the other ones too. + + gtk/Makefile.am: Don't include auto-generated files into make dist tarbal + We have various files which are auto-generated which currently get included + into the tarbal, yet they are part of CLEANFILES, so the first make clean + removes them, which is rather weird. Use nodist_foo_SOURCES to make them + not end up in the tarbal. + + generated_[de]marshallers[1].c, are special as autogenerating those on + end user builds would mean requiring the end user to have pyparser installed, + so we add them to EXTRA_DIST and remove them from CLEANFILES. It may seem + weird to have them in nodist_... and then add them to EXTRA_DIST, + but this patch also adds an explict depenency on the autogenerated files + to the non autogerated ones: + $(libspice_client_glib_2_0_la_SOURCES): spice-glib-enums.h + + Leaving generated_[de]marshallers[1].c in libspice_client_glib_2_0_la_SOURCES, + would cause it to get a dep on autogenerated files, and thus get regenerated + itself no matter what, defeating the purpose of having them in dist in the + first place. + +2011-09-01 Hans de Goede <hdegoede@redhat.com> + + spice_usb_device_get_description fixups + 1) Fix spice_usb_device_get_description compilation when building without + usb support + 2) Don't return "Unknown" when the device param is NULL, the caller should + g_free the returned string, so we cannot return a const string + 3) Fix the existing callers to actually g_free the result of + spice_usb_device_get_description. To avoid code duplication this patch + makes usb-device-manager prefix the error it gets from the usbredir-channel, + so that users of the auto-connect-failed signal can use the error as is. + + usbredir: provide out own libusb_strerror for now + libusb_strerror is not going upstream because of i18n worries, provide + our own for now. + + usb-device-manager: Add a auto-connect-failed signal + And use it in spicy to inform users of auto redirect failures (usually due + to insufficient rights on the /dev/bus/usb device nodes). + + usb-device-manager: Add a spice_usb_device_get_description() method + This is just a place holder for now. A better implementation requires + gusb changes, and I hope there will be an official gusb release by the + time I get around to fixing this up. + + Drop VOID:BOXED user marshaller + We were generating a user marshaller for VOID:BOXED, but there is a standard + marshaller for that, use that instead. + +2011-08-31 Marc-André Lureau <marcandre.lureau@redhat.com> + + doc: various improvements + + doc: update to include USB redirection + +2011-08-30 Hans de Goede <hdegoede@redhat.com> + + Remove spice-client-gtk.defs from git (as it is auto-generated) + spice-client-gtk.defs gets autogenerated (but only when building for + gtk2). Having it in git means having to keep it in sync with the public + API manually, which requires doing a gtk2 build before committing each + time one makes changes to the public API. + + As with any autogenerated files, this really does not belong in git, + removing it from git removes the need for the manual syncing. + + Also add it to make clean, and change gtk/Makefile.am so that + the contents on EXTRA_DIST don't depend on how ./configure was run + making "make dist"-s result depend on ./configure flags is not a good idea. + + Remove gtk/.gitignore + gtk/.gitignore gets autogenerated and thus should not be part of git. + + It currently being part of git is esp. annoying since depending on + wether you're building for gtk2 or gtk3, lines like: + /SpiceClientGtk-2.0.gir + /SpiceClientGtk-2.0.typelib + /libspice-client-gtk-2.0.la + + Keep disappearing from it, leading to these changes accidentally + getting included into whatever commit your working on. + + spice_gstaudio: s/SpiceGstAudio/SpiceGstaudio + We should either have SpiceGstAudio && spice_gst_audio or + SpiceGstaudio && spice_gstaudio, not SpiceGstAudio && spice_gstaudio + like we have today. This patch fixes this by replacing SpiceGstAudio + with SpiceGstaudio. We can do this since this is only used internally. + + Rename my_foo private datatypes to MyFooPrivate + We were using the gobject standard notation of MyFooPrivate everywhere + except for 3 places, this brings these 3 into sync, with what we do elsewhere. + + Add auto_usbredir property to spice-widget + + spice-session: at a spice_session_has_channel_type method + + Add an USB device manager + + Add an usbredir channel + + Add a private copy of gusb + While working on usb redirection support for spice-gtk I needed some + code to integrate libusb into glib's mainloop amongst other things. I ended + up borrowing code from colord for this. Richard (the colord author) and I + quickly agreed that doing generic glib bindings for libusb is a good idea, + akin to the gudev bindings for libudev we've called our WIP on this gusb: + https://gitorious.org/gusb + + Since this very much is a WIP, the API is nowere near stable, so for now + we bundle a copy of this code with spice-gtk. When gusb has an official + release out the door with a stable API we should switch to that. + + spice.proto: Add usbredir channel + + spice-channel: Reset SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION on disconnect + Our disconnect handler clears the common_caps array so that a new + connection starts with a clean slate. But in our constructor we set + the SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION in common_caps as starting + cap. Do the same on disconnect, so the behavior of a re-using a channel + after disconnect is the same as using a fresh channel. + +2011-08-17 Hans de Goede <hdegoede@redhat.com> + + spice-channel: fix writing a byte twice when a write blocks + When a write blocks, and thus ret == -1 (and the gerror matches EAGAIN) we + still do offset += ret, causing the last written byte to be send twice. + Lets not do that :) + + spice-widget: release_keys on focus out + This fixes alt getting stuck in the guest when the user alt-tabs away from the + spice-widget (thus making it see the alt press but not the release) and then + closing it without giving it the focus back (by using the windows close button + for example). + + Note that doing this on focus out (when we know we may be missing key releases + afterwards) makes a lot more sense then doing this on focus in, and with + the release_keys on focus out I don't really see a reason any more to do it + on focus in. But I'm leaving it in on focus in just in case, it certainly + cannot hurt there. + + spice-widget: remove keyboard_grab_count / keyboard_grab_time hack + With the filtering of focus in / out events caused by grabs we should no + longer need this. + + spice-widget: ignore focus in / out events caused by keyb ungrab/grab + As documented in XGrabKeyboard(3): "The XGrabKeyboard function actively grabs + control of the keyboard and generates FocusIn and FocusOut events." + + Note that for some reason this only happens when we call XGrabKeyboard + from our enter_event / leave_event callbacks and not from our focus_in / + focus_out callbacks? Either way we still need to filter these out. + + Filtering these out fixes 4 issues: + 1) keyboard_have_focus now no longer gets unset when the keyboard is grabbed, + making USB auto redirection when focussed actually work + 2) Before this patch, if you pressed alt and then (accidentally) moved the + cursor out of the spice-widget window before pressing a second key, + the focus in event would clear the keyboard status causing the guest to no + longer see alt as pressed and register the second key press as a regular + keypress rather then as alt-foo. + 3) It allows us to remove the keyboard_grab_count / keyboard_grab_time hack + from try_keyboard_grab, although since we are no longer doing an + ungrab on focus out, this likely could have been removed before. + I will do this in a separate patch for easier reverting if necessary. + + spice-channel: Fix a possible race triggered by spice_channel_iterate_write + Fix a race between spice_channel_buffered_write and + spice_channel_iterate_write. + +2011-08-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + data: fix spicy.nsis.in to include right libraries + + build: fixes build with gtk3 on win32 + + build: warn and instruct if valac is missing + + gtk: implement coroutines using Windows fibers + +2011-08-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + use _setjmp/_longjmp to speed up coroutine switching + As described in http://www.1024cores.net/home/lock-free-algorithms/tricks/fibers + +2011-07-29 Christophe Fergeau <cfergeau@redhat.com> + + mjpeg: don't leak last stream image + When a stream is destroy, the memory allocated to handle the mjpeg + decoding is freed by calling stream_mjpeg_cleanup. However, the + memory allocated to contain the last uncompressed stream image + wasn't freed. + + mjpeg: remove wrong g_return_if_fail + After calling jpeg_read_scanlines, spice-gtk checks that we read + the amount of lines we expected, and if not, it returns early. + This is doubly wrong: + + * jpeg_read_scanlines is documented as returning at most the number + of lines requested, but it also warns that an application shouldn't + rely on getting exactly the number of scanlines requested. In this + case, if rec_outbuf_height is bigger than 1, we'll get a short read + on the last line of odd-sized images, thus triggering the + g_return_if_fail + + * returning from this function without calling jpeg_abort will cause + libjpeg to abort next time we use it because jpeg_start_decompress + was called before + + This commit removes this check and early return. + + mjpeg: restrict use of i and j + Using i and j as variable names that are used from one loop to the + other isn't really readable, and makes the code more fragile than + it could be. This commits adds a "lines_read" variable which is more + expressive than "j", restricts "j" lifetime to the loop where it's + used, and it removes the "i" variable and uses counters provided + by libjpeg to iterate all the image lines. + It also has the side-effect that if jpeg_read_scanlines returns a short + read (less lines than expected are read), "dest" won't go out of sync but + will be set to the right place at the end of the loop. + + mjpeg: properly abort decompression in error path + spice-gtk jpeg decompression code honors libjpeg's recommended size + for its output buffer to improve performance. However, when this + recommended size is too big, it just gives up on the decompression + process by returning early from the function. But since + jpeg_start_decompress has been called to compute this recommended + size, the decompression must be aborted before returning, otherwise + libjpeg will get in an inconsistent state and will abort next time + we try to use it. + This commit also moves the check that the recommended size isn't + too big out of the decompression loop because it shouldn't changed + during decompression. + +2011-07-28 Christophe Fergeau <cfergeau@redhat.com> + + fix integer marshalling helpers on big endian + They were trying to convert the destination pointer to an integer before + trying to dereference it. The initial conversion was meant to be a cast + to a pointer of the right size, not to an integer. + + fix typo in big endian code path + uint63_t should be uint64_t + +2011-07-26 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix libtool versionning + As pointed out by Daniel P. Berrange: + "Arrggh ! There's a typo there. You want '-version-info' not + '-version-number'. The latter directly sets the major/minor + soname values hence why you keeping seeing incompatible versions :-(" + +2011-07-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + Release v0.7 + + build: update library version + client-glib interfaces have been changed or added, but binary compatibility has been preserved, change to current+1:0:age+1 + + client-gtk updated code, same API: increment revision. + + build: fix make distcheck + + build: fix introspection warnings + The only one left is related to GOptionGroup, which is not boxed. + + gtk/controller: fail if SPICE_XPI_SOCKET is not provided + Instead of trying to connect to a '(null)' socket. + +2011-07-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: snappy/spicy-stats move connection option to main group + + gtk: update spicy to use new option API + + gtk: add spice_get_option_group() + + gtk: add color-depth and disable-effects options + +2011-07-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add spice_strv_contains in util-priv.h + + build: fix .pc Requires + +2011-07-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: avoid doing GdkWindow operations if widget is not realized + + gtk: honour CURSOR_FLAGS_NONE by hiding cursor + + gtk: comment channel_new() returns a weak reference + And add a few sanity checks. + + gtk: add glz_decoder_window_clear, to recycle decoder + +2011-07-14 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: rework widget destroy/dispose() + Make sure to remove handlers during dispose. + Destroy is purely a gtk+ thing, so let the widget do the job. + + This solves a refcount/crash issue found with virt-manager. + +2011-07-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/doc: improve the generated gtk-doc a bit + + Merge remote-tracking branch 'teuf/master' + +2011-07-13 Christophe Fergeau <cfergeau@redhat.com> + + document SpiceSession properties + + smartcard: add smartcard API doc + +2011-07-12 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: remove false warning + +2011-07-12 Daniel P. Berrange <berrange@redhat.com> + + gtk: remove double symbol definition + + gtk/pulse: fix memory leak + +2011-07-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: allow setting color depth + + gtk/spicy: add disable-effects option + +2011-07-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/smartcard: make smartcard init async + + gtk: add SPICE_CLIENT_ERROR + + gtk/debug: put package version in session_init + +2011-07-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: remove surface cache, why do we need it? + +2011-07-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/channel-cursor: refcount display_cursor, make explicit the life of rgba + + gtk/smartcard-manager: remove useless trailing ; + +2011-07-05 Christophe Fergeau <cfergeau@redhat.com> + + cursor: don't leak uncached cursors + When the cursor channel creates a new cursor, if the message + indicates not to cache it, the cursor is leaked after being used. + This commit fixes that, though I'm not really satisfied with it. + + ==22568== 378,432 bytes in 162 blocks are definitely lost in loss record 7,699 of 7,699 + ==22568== at 0x4A0649D: malloc (vg_replace_malloc.c:236) + ==22568== by 0x4E624CF: spice_malloc (mem.c:88) + ==22568== by 0x4E4F1C4: set_cursor (channel-cursor.c:323) + ==22568== by 0x4E4FA29: cursor_handle_set (channel-cursor.c:469) + ==22568== by 0x4E4FD19: spice_cursor_handle_msg (channel-cursor.c:548) + ==22568== by 0x4E30292: spice_channel_recv_msg (spice-channel.c:1641) + ==22568== by 0x4E3062A: spice_channel_iterate_read (spice-channel.c:1776) + ==22568== by 0x4E307F9: spice_channel_iterate (spice-channel.c:1820) + ==22568== by 0x4E30EE4: spice_channel_coroutine (spice-channel.c:1968) + ==22568== by 0x4EE48A2: coroutine_thread (coroutine_gthread.c:77) + ==22568== by 0x302E4683A5: g_thread_create_proxy (gthread.c:1955) + ==22568== by 0x302C807AF0: start_thread (pthread_create.c:305) + +2011-07-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: s/SmartCard/Smartcard/g + + gtk: total-read-bytes is ulong + As pointed out by Christophe on the ML. + +2011-07-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: remove warning if !USE_SMARTCARD + + Merge commit 'refs/merge-requests/16' of ssh://gitorious.org/spice-gtk/spice-gtk into merge-requests/16 + +2011-07-02 Alon Levy <alevy@redhat.com> + + gtk: add spicy-stats test app + + spice-channel: add property total-bytes-read + + spice-channel: export spice_channel_type_to_string + +2011-07-01 Christophe Fergeau <cfergeau@redhat.com> + + prepend smartcard cmdline options with --smartcard + This is consistent with what spicec does, and is also less + confusing since other certificates can be passed on the command + line (for client/server host authentication). + + add --smartcard option to spicy + People starting spicy will not always want their smartcard data + to be forwarded to the guest they're connecting to. Currently, + smartcard events are unconditionnally forwarded to the server if + spicy was compiled with smartcard support. This commit adds a + --smartcard option that must be used in order to enable smartcard + support in the client. By default, smartcard data won't be forwarded + to the server unless this option is specified. + +2011-06-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/smartcard: make cacard dependency optional without breaking API + +2011-06-26 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/smartcard: remove g_assert + +2011-06-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + TODO: update + + build-sys: fix disable-smartcard broken earlier + +2011-06-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/smartcard: add a couple of debug + + gtk/smartcard: simplify a little spice_smartcard_manager_init_libcacard + +2011-06-23 Christophe Fergeau <cfergeau@redhat.com> + + use new @ifdef directive for smartcard messages + We don't want to conditionally compile the smartcard messages + depending on whether USE_SMARTCARD is set or not, we can now use + the @ifdef attribute for that. + + handle @ifdef on messages and channels + + allow attributes on channel elements in .proto files + We want to be able to add an @ifdef annotation to optional messages + For example, we want to compile in the smartcard messages only if + libcacard is available + + add ifdef/endif methods to spice code generator + These methods will be needed to be able to make some fields optional + in spice.proto + + fix compilation when libcacard isn't installed + + set menu actions sensitivity for software smartcards + Make sure menu actions are only sensitive when we are using a + software smartcard reader, and properly update the sensitivity + depending on the presence or not of a software smartcard in the + software reader. + + add smartcard actions to spicy + Add code to add/remove a software smartcard in spicy UI. These + 2 entries were added as items in the Input menu. They are not + grayed out for now if there is no software reader available. + + add software smartcard reader support + + use user-provided certificates when init'ing libcacard + + read certificate information from command line + When using a software card reader, one needs to pass 3 certificates + to be used to simulate the smartcard (and optionnally the path to + a certificate database). This commit adds support for --certificates + and --certificate-db command line options to do that. + + add smartcard properties to SpiceSession + To handle software smartcards, we need to be able to pass the + certificates to use for the smartcard as well as the database where + these certificates can be found. This commit adds "certificates" + and "certificate-db" properties to make this possible. + + handle smartcard channel in SpiceWidget + + handle smartcard channel in spice_channel_new + + initialize libcacard + + don't always serialize messages sent to the server + The communication between spice clients and servers on the smartcard + channel can be initiated either by the client or by the server. + It's initiated by the client for smartcard reader events (reader + hot(un)plug, card insertion/removal), or it can be initiated by the + server when it wants to query the certificates available on the + smartcard. + When communication is initiated by the client, we want to serialize + the messages we sent, ie we don't want to send a message if we + haven't received yet the answer to the previous message. + However, when it's the server which initiates the communication, + we don't want to use this serializing mechanism. + + This commit adds a "serialize_msg" boolean to be able to disable + message sending serialization as needed. + + forward APDU requests from server to smartcard reader + These requests are sent by the server when trying to read the + certificates from the smartcard. + + handle messages from spice server + + serialize sending of smartcard channel messages + Messages sent to the spice server by the smartcard channel have to + be serialized: before sending a message, the channel has to wait + for the server answer to the previous message. Add a GQueue to be + able to queue several messages to the server while we wait for the + answer to an earlier message. + I think the reason why that serialization is needed is to be able + to deterministically assign IDs to readers on reader addition. We + have no way to match a message from the spice server with the + message to the server that triggered this reply, which means that + if we could send several reader additions to the server without + waiting for answers, when the server answers, we wouldn't know + which reader it's trying to assign an ID to. + + send messages to spice server on reader/card events + + add basic callbacks for smartcard events + Now that the smartcard manager sends event for smartcard readers, + the smartcard channel has to do something with them. For now, we just + add basic callbacks which don't try to forward these events to the + spice server. However, we start adding the glue needed to handle + the fact that plugging of smartcard readers and creation of these + readers in the spice server will be asynchronous. + After receiving a "reader addition" command, the spice server sends + back an ID to identify this reader which must be used in all other + requests (card insertion, removal and reader removal) to identify + this reader. However, if the server is slow to send back this ID, + there's a window when we can get additional events for the reader + that is being added that we can't send right away to the server + because we don't know the ID to use. That's why we add the various + pending_* hashes in this commit, to be able to keep track of the + requests that will have to be sent once the spice server has + assigned an ID to the reader. + + add smartcard bits to spice.proto + +2011-06-22 Christophe Fergeau <cfergeau@redhat.com> + + emit signals in reaction to libcacard events + + add signals for smartcard events + Add signals which will be emitted when a reader appears/disappears, + or when a smartcard is inserted/removed. + + add boxed type for VReader + VReader is a type defined in libcacard which contains all the + information we need ot handle card readers. Since it's refcounted, + we can make it a boxed type for use in signals. + + add smartcard monitor GSource + This source gets events from libcacard and inserts them into + a regular glib mainloop. The smartcard manager will then emit + signals in reaction to the events it got from libcacard. + +2011-06-22 Marc-André Lureau <marcandre.lureau@gmail.com> + + build-sys: some minor cleanup + +2011-06-22 Christophe Fergeau <cfergeau@redhat.com> + + add --enable-smartcard configure flag + + add smartcard channel and smartcard manager skeletons + + improve debug log on coroutine start + + factor base message handling in SpiceChannel + Currently, every channel has to define all the server messages it + handles, including the "generic" ones. Since it's error prone (easy + to forget the handling of default messages in new sources), it's + better to move this handling to the base channel class, and to call + the parent method when the message is unknown in the ::handle_msg + method. + + On top of this, another factoring that can be done is to make the + message handling function generic instead of reimplementing it in + every class. Each class would only have to register its own + (class-specific) set of handlers. + + Conflicts: + + gtk/channel-playback.c + gtk/channel-record.c + + display more options in default --help + When running spicy --help, very few options are shown. I didn't + notice at first that it was possible to specify the spice server + host/port/... showing them in the default help output should make + these options more obvious. + +2011-06-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: get rid of duplicated channel_desc table + + gtk/gstaudio: add volume control support + +2011-06-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/audio: announce volume capability + + add git .mailmap + + gtk/pulse: add volume control support + + common: add volume messages + + spice.proto: updated with volume messages + + playback/record: add audio volume properties + +2011-06-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: add accel menuitem property + + gtk/controller: change namespace to SpiceCtrl + +2011-06-17 Christophe Fergeau <cfergeau@redhat.com> + + gtk/spicy: fix buttons in connect dialog + Use proper button order (confirmation should be bottom right) and + use a "Connect" button instead of "Ok". + +2011-06-14 Alon Levy <alevy@redhat.com> + + channel-display: destroy_stream: fail if streams is NULL + +2011-06-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: fix connection events on namedpipe + Strangely, Wine was working fine with the NamedPipe handle itself. + + But WinXP wants the Event handle, obviously. + +2011-06-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: build win32 controller pipe name + +2011-06-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: rule out clicks in outside region + Not so great change: we should have a grab on the pointer when + pressing, to receive the release event even if outside the + region. Unfortunately, grabs are single widget for now. + + gtk: oops, forgot to put signal detail first + +2011-06-08 Marc-André Lureau <marcandre.lureau@gmail.com> + + gtk/widget: keep a ref on the session + This is to make more explicit that the session isn't owned by the + widget display, but rather shared. + + Also, it makes it easier to deal with dispose() since there is + explict referencing. + + gtk/session: allow spice_session_disconnect() to be called several times + + gtk/channel: add more runtime check, and make sure any pending idle associated are removed + +2011-06-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + Merge commit 'refs/merge-requests/14' of ssh://gitorious.org/spice-gtk/spice-gtk into merge-requests/14 + +2011-06-07 Christophe Fergeau <cfergeau@redhat.com> + + add really basic GDK GnomeRR backend + It doesn't know about available resolutions, nor about clones, + rotations, ..., it can't trigger resolution changes, but hopefully + it will be enough for basic GnomeRR support in the mac port. + + configure.ac: add defines for windows and osx + Check for gtk+-win32/gtk+-osx to know when we should define + HAVE_WINDOWS/WITH_DISPLAY_WINDOWS and HAVE_QUARTZ/WITH_DISPLAY_QUARTZ + + This is better than the old scheme that blindly tried to detect + libx11, and chose between x11/windows depending on only this + test. + We probably should check that only one of windows/x11/quartz is + enabled at once. + NB: for now the QUARTZ defines are not used since we will be + using a generic GnomeRR backend instead of having our own + OSX backend. + + configure.ac: only check for X11 libs on X11 builds + No need to try to detect xrandr or xkb headers when we won't be + doing an X11 build. This is even detrimental on Mac OSX when + we want to attempt a native build but have the xkb headers installed. + + configure.ac: simplify --with-x11 processing a bit + + configure.ac: improve X11 detection + Use gtk-x11-[23].0.pc to detect whether we want an x11 build or + not. Don't AC_SUBST X11_CFLAGS and X11_LIBS since they are unused. + + configure.ac: group all X11 checks + Gather all x11 related checks in the same place + +2011-06-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/win32: interecept low level keys - fix alt-tab and such + + gtk: improve gstaudio backend + Do not timestamp gst audio buffers, since they are continuous anyway + and it fixes directsoundsink stuttering + + Also, add a new SPICE_GST_AUDIOSINK environment variable to play with + sink parameters + + build/win32: they broke libjpeg again + +2011-06-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/win32: gtk maps LAlt & LCtrl to Alt and Ctrl keycode, but they are missing from keymaps.csv + +2011-06-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: update spicy.nsis installer + +2011-06-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix windows build with recent mingw64 + +2011-06-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: remove unused c++ check + + gtk/spicy: add rudimentary grab-sequence configuration setting + +2011-05-28 Christophe Fergeau <cfergeau@redhat.com> + + fix miscellaneous memleaks + Fix various memleaks that were reported by valgrind. + + plug a memleak in ChannelMain::_channel_new + ChannelMain::_channel_new was leaking memory in an error path. + Unconditionnally free the used memory, which has the added benefit + of making the code simpler. + +2011-05-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: load ca-file if SPICE_SESSION_VERIFY_SUBJECT + Fix SSL verify to work like spicec, not sure what I am doing there, but it works. + + gtk: update python binding generated file + + gtk: log spice-gtk version when creating a session + +2011-05-25 Christophe Fergeau <cfergeau@redhat.com> + + fix make distcheck + + make perl-Text-CSV optional for tarball builds + Ship the files generated using perl-Text-CSV in the tarball so that + end-users (as in "people compiling from a tarball") won't need to + have perl-Text-CSV installed. + +2011-05-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: free some more objects when quitting + +2011-05-25 Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + + Connect on recent connection item activation + Now (commit 27df918) that we already gather connection information when + user (single)-clicks a recent connection item, we can safely use the + selected recent connection when user activates (double-clicks) it. + + RecentChooser should act on single-click + Fill-in the connection dialog fields as soon user selects a recent + connection. + + Minor coding-style fix + Don't use mix of tabs and spaces. + + Get rid of redundant argument + + Minor clean-up + Prefer 'if/else' over 'switch' when dealing with only 2 possibilities. + +2011-05-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + Merge branch 'merge-requests/11' + +2011-05-25 Christophe Fergeau <cfergeau@redhat.com> + + sync protocol files with spice + + remove duplicate headers from Makefile.am + Headers needed for map-file generation were listed twice, once in + libspice_client_glibinclude_HEADERS and once in _SOURCES. It's ok + to only have them in _HEADERS. Order channel names alphabetically + while I'm touching this part of Makefile.am + + remove G_GNUC_CONST from get_type functions + These functions call g_type_register_* the first time they are + called which is not G_GNUC_CONST so this attribute can't be used + here. This had the side effect of making these functions not appear + in sym-file after running make update-sym-file. + +2011-05-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add SSL ciphers session property + + THANKS: update + + Merge commit 'refs/merge-requests/10' of ssh://gitorious.org/spice-gtk/spice-gtk into merge-requests/10 + +2011-05-23 Christophe Fergeau <cfergeau@redhat.com> + + add const to arrays in marshalling functions + + fix copy & paste error in ptypes.py + + remove duplicate #include + + fix wrong comment in spice_spice_channel_send_msg + + s/interruptable/interruptible + +2011-05-23 Daniel P. Berrange <berrange@redhat.com> + + Fix missing OS-X keymapping for letter 'A' + The keymap-gen.pl script was not correctly distinguishing + keycodes with a value of '0', from undefined keycodes. All + were skipped. This meant that the mapping for OS-X ANSI_A + key was lost (since it has value 0). + + For similar reasons the XQuartz mapping for the letter A + was also lost. + + * src/keymap-gen.pl: Fix handling of 0 vs undef for keycodes + * src/keymaps.csv: Remove bogus 0x0 entry in OS-X keymap + + Add missing keytable entry for KEY_KATAKANAHIRAGANA + * src/keymaps.csv: Add XT code for KEY_KATAKANAHIRAGANA + +2011-05-23 Christophe Fergeau <cfergeau@redhat.com> + + include stddef.h in continuation.h + It uses size_t so it needs it to get a definition for this type. + If it's not there, this causes build breakage on OS X + +2011-05-23 Attila Sukosd <attila.sukosd@gmail.com> + + define MAP_ANON as MAP_ANONYMOUS if needed + Mac OS X doesn't have MAP_ANONYMOUS, only MAP_ANON, so use MAP_ANON + when MAP_ANONYMOUS isn't defined. + +2011-05-23 Christophe Fergeau <cfergeau@redhat.com> + + ssl_verify: include <string.h> + ssl_verify.c is using memcmp which comes from string.h, this was + breaking compilation with -Werror -Wall on Mac OS X + + link with gthread when appropriate + The corouting gthread code and spicy are using gthread functions + but were no linked against the gthread library. This causes build + failures on older glibs where gthread isn't mandatory when using + glib. + + gnome-rr: use g_object_notify instead of g_object_notify_by_spec + The latter was added in glib 2.26, and we only require glib 2.22 + +2011-05-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + display: fix build error GLib <2.26 + https://bugs.freedesktop.org/show_bug.cgi?id=37443 + +2011-05-20 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: correctly close namedpipe after calling close() + + gtk/controller: add some missing clean up of namedpipe + + gtk/controller: forgot to dispose stream as well + + controller: stick to 2.22 API + +2011-05-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix build with latest mingw + +2011-05-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: got NamedPipe basic working + +2011-05-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/controller: start NamedPipe support (compile with mingw32) + +2011-05-11 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: restore correctly UI elements visibility state + +2011-05-10 Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + + gtk: some code cleanup + +2011-05-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: spicy - leave fullscreen when grab sequence is pressed + Workaround since accels are now disabled.. Ideally we either have a + different key sequence or we use Vinagre UI + + gtk: fix spicy grab key sequence + + gtk: warn on invalid key sequence + + gtk: add grab-keys-pressed signal + + gtk: don't ungrab keyboard on focus-ous + Mainly to avoid the crazy loop: + focus-in > grab -> focus-out -> ungrab -> focus-in + on kde & gnome-shell. + + gtk: keyboard handling improvements + - spicy: disable accels/mnemonics when grabbed + + gtk: extra check only compiled if !NDEBUG + +2011-05-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: get rid of a useless warning + + gtk: return RGB -> BGRX color conversion for non-turbo jpeg + +2011-05-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: use faster jpeg decompression by default + +2011-05-08 Marc-André Lureau <marcandre.lureau@gmail.com> + + gtk: warn if received invalid frame timestamp + +2011-05-07 Marc-André Lureau <marcandre.lureau@gmail.com> + + gtk: speed up mjpeg decompression + Remove custom rgb->argb functions, and remove fancy post-proc (which I + don't think were applied, but we now do the same as spicec) + + gtk: sync audio with gst backend + +2011-05-06 Marc-André Lureau <marcandre.lureau@gmail.com> + + build: update README with depedencies + + gtk: warn unsupported channel type with a description + +2011-05-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: adjust overall playback latency to 100ms + The previous parameters didn't adjust overall latency. Adjusted to + 100ms overall latency lower cpu load, and improve video flickering + + (damn /me suck at PulseAudio client-side...) + +2011-05-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix SASL auth failed + Signal correctly to the client that AUTH failed. + + Before, we only had a IO error on channel disconnection. + +2011-05-03 Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + + configure.ac: Use gtk+ 3.0 be default + Hi Zeeshan!! + +2011-05-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + TODO: fix wrong mouse ungrabbing for dragndrop + +2011-04-27 Christophe Fergeau <cfergeau@redhat.com> + + configure.ac: remove setting default C(XX)FLAGS + automake/autoconf already set them for us to -g -O2 if there are + no flags defined. + + configure.ac: use AC_LANG_SOURCE + Recent autoconf complains when AC_COMPILE_IFELSE is used without + using AC_LANG_SOURCE to generate the code snippet to compile. Add + the missing AC_LANG_SOURCE call to SPICE_CC_TRY_FLAG to make it + quiet. + + configure.ac rework introspection detection + When running autogen.sh without having gobject-introspection, this + should give a slightly nicer error message. It currently errors out + with + gtk/Makefile.am:450: HAVE_INTROSPECTION does not appear in AM_CONDITIONAL + + After the patch the error will be + checking for GOBJECT_INTROSPECTION... yes + ./configure: line 21307: syntax error near unexpected token `0.6.7' + ./configure: line 21307: `GOBJECT_INTROSPECTION_CHECK(0.6.7)' + +2011-04-18 Christophe Fergeau <cfergeau@redhat.com> + + spicy: disable Ctrl+W/Close keyboard shortcut + The keyboard shortcut for the Close gtk action isn't disabled, + which leads to spicy closing when trying to use Ctrl+W in the guest. + All other problematic shortcuts are disabled, but in this case the + disabling was commented out. Reenable it to prevent people from + accidentally closing spicy when pressing ctrl+w + + spicy: fix keyboard shortcuts in comments + The various action entries have a comment about the keyboard + shortcut that is being disabled. However, all these comments were + copied from the "Quit" action and were all referring to Ctrl-Q. + This commit puts the right keyboard shortcuts in the comments + + spicy: remove non-needed keyboard shortcut disabling + GTK_STOCK_CONNECT doesn't have an associated keyboard shortcut + so there is no need to explicitly disable it. + +2011-04-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + NEWS: update for v0.6 + + TODO: update + + gtk/display: move some RANDR code to X11 file + + build: fix make distcheck + +2011-04-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + Merge commit 'refs/merge-requests/6' of git://gitorious.org/spice-gtk/spice-gtk into merge-requests/6 + + gtk/map-file: fix spice_main_send_monitor_config function name + +2011-04-11 Marc-André Lureau <marcandre.lureau@gmail.com> + + gtk/controller: fix build with non-default arguments + +2011-04-11 Christophe Fergeau <cfergeau@redhat.com> + + gtk: fix "set but not used" gcc 4.6 warnings + Since we are compiling with -Werror, this was breaking compilation. + +2011-04-11 Alon Levy <alevy@redhat.com> + + python_modules/codegen.py: fix indent error in an unused function + + demarshaller/marshaller fix gcc 4.6.0 + python_modules/demarshal.py and marshal.py fixes for gcc 4.6.0 + warning about set but unused variables. The fixes disable creating + of variables mem_size when they are not used (demarshall) and + declaring a src variable when the message doesn't use it (marshal). + + You need to touch *.proto after applying this (should add a Makefile + dependency). + + codegen: avoid creating out if not used (fix gcc 4.6.0 warning) + + mingw32 build: python_modules/marshal: use unsigned for for_loop index variable + +2011-04-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: do not show again toolbar when going full-screen, if mark received + + gtk: calling connect() on a connecting channel is fine + This avoid problems where different display shares the same input + channel and try to connect two times. + + gtk: allow to drag-and-drop between displays / windows + + gtk/controller: install spice-controller library + +2011-04-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + common: fix build error of used uninitialized + CC sw_canvas.lo + cc1: warnings being treated as errors + ../common/sw_canvas.c: In function 'canvas_draw_text': + ../common/sw_canvas.c:1037:16: error: 'pos.x' may be used uninitialized in this function + ../common/sw_canvas.c:1037:16: error: 'pos.y' may be used uninitialized in this function + make[4]: *** [sw_canvas.lo] Error 1 + +2011-04-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + TODO: update + + build: fix gtk/controller/Makefile valac line which had custom.vapi + + Merge commit 'refs/merge-requests/5' of git://gitorious.org/spice-gtk/spice-gtk into merge-requests/5 + + gtk: don't send MonitorConfig after agent start + We don't know yet what will be the guest previous configuration. + + Ie, what should we send otherwise? Current hardware configuration? + This works badly with windowed mode, where we expect the same windows + to be displayed on reconnection. + + gtk: introduce more complete spice_main_send_monitor_config() + Since it's unclear yet how MonitorConfig should be used depending on + use case (full-screen vs windowed) we prefer to make a public api so + that the client implementation can send it when it is the most + appropriate time. + + gtk: add disable-display-position + + gtk: remove unnecessary invalidate mark signal + + gtk: send FALSE mark when destroying the primary surface after 1s... + This is similar to what is done in spicec. + + gtk: hide the cursor after setting it + So that when we move the cursor again, we can show the right one + + gtk/spicy: hide the display if mark is FALSE + + gtk/spicy: update status of all windows + + gtk/spicy: only show window when we receive the mark + + gtk: not having a window is not critical, if the widget is not yet shown + +2011-04-08 Hans de Goede <hdegoede@redhat.com> + + gtk: fixup clipboard_by_guest tracking + clipboard_by_guest tracking was used more or less for 2 things, to keep track + if the agent has clipboard data ready to send, and to see if we have done a + clipboard_set_with_data on behalf of the guest agent. + + This patch splits the tracking of the 2, fixing several issues: + 1) spice_display_paste_from_guest would not work if since receiving + the grab from the agent some other app has copied something to + the client clipboard. + 2) We would do a clipboard_clear unconditionally even if we were + not the clipboard owner in the client (iow some other app has + done a clipboard_set_with_data since out last one). + + This patch changes the meaning of the clipboard_by_guest boolean to just + track if we've done a clipboard_set_with_data on behalf of the guest + and are the last one to have a done a clipboard_set_with_data (iow we are the + client os' clipboard owner). It adds a checks to clipboard_release to + only call clipboard_clear if we are the current ownerm fixing 1). + + This patch uses nclip_targets to keep track of the agent having data + available which we could paste, fixing 2). + + gtk: Clear hasdata when we do a clipboard_set_with_data + When we call gtk_clipboard_set_with_data to set the client clipboard + to the targets reported as available by the agent, the clipboard no + longer has data in the sense that it has data which is interesting + for spice_display_copy_to_guest, so clear clip_hasdata whenever we + call gtk_clipboard_set_with_data, + + gtk: receiving a grab from the agent implies releasing our own + By setting d->clip_grabbed[selection] to FALSE when we receive a grab from + the agent, we can remove the weird "if (!d->clipboard_by_guest[selection])" + check from clipboard_owner_change, and we fix spice_display_copy_to_guest not + working in the following case: + 1) autoclipboard share disabled + 2) Copy something to the clipboard in the client + 3) Send it to the guest by calling spice_display_copy_to_guest + 4) Copy something to the clipboard in the guest + 5) Tried to send the client clipboard to the guest again by calling + spice_display_copy_to_guest (again). + + 5) would not work because d->clip_grabbed[selection] would still be true in + spice-gtk's view, where as the agent no longer sees the clipboard as grabbed + by the client since it send a grab itself. + + gtk: use a separate var to keep track of self caused new clipboard owner events + Also change 0/1 to FALSE/TRUE in touched code. spice-widget seems to be + using all 3 of: 0/1 false/true and FALSE/TRUE for booleans. The glib convention + is FALSE/TRUE. + +2011-04-05 Hans de Goede <hdegoede@redhat.com> + + gtk: take selection into account in clipboard_release + +2011-04-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: only release clipboard when neither guest nor client own it + 08:55 < hansg> elmarco, this is from vdagent.log with debugging enabled. What is happening is that the last thing done was a primary + selection in the client, so vdagent owns the clipboard in the guest (on behalf of spice-gtk), then something gets selected + inside the guest, the agent sends a grab to spice-gtk, which then does a gtk_clipboard_set_with_data, this triggers an + clipboard_owner_change which sends a release message to the agent + 08:56 < hansg> To which the agent then responds by dropping it, and logging: + 08:56 < hansg> primary: received release while not owning client clipboard + 09:11 < elmarco> hansg: but this bug we are talking about is not related to multi-clipboard right? + 09:11 < elmarco> and it's only a warning in vdagent, things works as expected otherwise, right? + 09:11 < elmarco> the bug was thee before I suppose + 09:12 < hansg> right, they work because vdagent is diligent and sees the client sends a release while it is not owning the clipboard. The + diligence is mainly there in case things race though (release on client racing with a grab on guest), not to make things + work with buggy clients :) + 09:13 < hansg> wrt: <elmarco> hansg: d->clip_grabbed is only for client-side grab, iirc + 09:13 < elmarco> ok, I think it's just an obscure area of the spec, where basically, we don't define exactly the "state machine" + 09:13 < elmarco> so the client is releasing his last client-side grab, because he had one before, but now, it is a guest grab + 09:13 < hansg> True (not exactly definging the state machine) + 09:14 < hansg> So to try again wrt the d->clip_grabbed, what happens there (which has the same cause) is: + 09:14 < elmarco> so, what it should do is just don't release the clipboard if it is switching from client-side to guest + 09:15 < hansg> gtk/spice-widget.c: clipboard_grab gets called, and does: + 09:15 < hansg> Hmm, hold on, I see what you mean wrt d->clip_grabbed now + 09:16 < elmarco> to me, it looks like the client made a grab and to complete it's cycle, it should release his grab + 09:16 < elmarco> but the order of things confuse vdagent and we should agree on something and document it + 09:18 < hansg> elmarco, I need some time to take a somewhat closer look at the spice-gtk code in this area, give me 1/2 an hour and I'l + get back to you + 09:20 < elmarco> from client 1. grab -> 2. grab <- 3. release -> or 1. grab -> 2. grab <- 3. no release + 09:21 < elmarco> I think state should not be mixed between client grab / release -> and guest grab/release <- + 09:22 < elmarco> so, overriding client grab by guest grab should release client grab + 09:23 < hansg> spicec and the linux agent both assume that after sending a grab they won't get back a release (for that selection). The + purpose of the release is to tell the OS that the agent resp, client no longer own the clipboard (by setting the owner to + None under X11), so that other apps can disable their paste menu item, etc. There is no need to do that (and actually + doing so would be a bug) if an other app now owns the clipboard. So if the other side claim + 09:23 < hansg> s ownership of the clipboard there is no need to tell it you're releasing your side, since it already assume you have + 09:24 < hansg> Scenarios to keep in mind are: + 09:24 < hansg> Seen from the client side: + 09:28 < hansg> client grabs clipboard + 09:28 < hansg> some app on guest becomes owner, guest sends grab, assume client release + 09:29 < hansg> some app on guest asks agent for clipboard data -> tells it to go away since the client no longer the owner + 09:29 < hansg> If it would not assume the release, there would be a window where it would think the client still owns the clipboard and + forward potential request to the client, even though the client no longer owns the clipboard + 09:30 < hansg> The thing to keep in mind is that the delivery of messages is not instant, so there is some window where the 2 sides are + out of sync. + 09:30 < hansg> I can see the logic in how you're advocating to do things, but that is not how they are currently done and I'm reluctant + to change this + 09:33 < elmarco> hansg: yeah, I don't think one solution or the other affect user experience, for me there is no gap if the client and + agent agrees, it's only protocol/implementation details + 09:33 < elmarco> since there was prior implementation, we can decide to follow it + +2011-04-04 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix multi-head support by sync the display cache + An image may come later from a different channel, even if it is referenced by another image. + + gtk: add some debugging in glz decoder and avoid crashes + + gtk: display now use the cache from the session + +2011-04-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: the caches are shared with the session + + common: get rid of abort() in canvases + + common: remove unnecessary outdated c++ debug + +2011-04-01 Christophe Fergeau <cfergeau@redhat.com> + + configure.ac: remove detection of WARN_UNUSED_RESULT + spice-gtk configure.ac has some code to detect if the compiler has + a special attribute to tag some functions so that they generate a + warning when their return value isn't checked. However, this test + is broken (the gcc attribute name is "warn_unused_result", not + "__warn_unused_result__" and WARN_UNUSED_RESULT is unused anyway + since spice-protocol provides SPICE_GNUC_WARN_UNUSED_RESULT. Thus + we can just drop that block of code from configure.ac + +2011-04-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + adding THANKS + +2011-04-01 Christophe Fergeau <cfergeau@redhat.com> + + configure.ac: remove unused tests + configure.ac had -fvisibility detection, but it's not used by + spice-gtk. It also has a --enable-static-linkage flag which isn't + used anywhere apart from in configure.ac, so remote this too. I + think the same effect as --enable-static-linkage can be achieved + using make LDFLAGS="-all-static" since we are using libtool. + +2011-03-31 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: correct CLIPBOARD_LAST so that array are sized correctly + + gtk: show cursor when cursor-move + + gtk: fix handling of incoming large clipboard data + The main fix was probably the agent_msg_pos guin8 -> guint, although I + modified the code for more clarity + + gtk: multi-clipboard improvements + +2011-03-30 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix make dist + + gtk/controller: add XPI controller code + + build: provide a conditional for WIN32 + + build fixup + + build: install spice-protocol.vapi + + build: check for vala if necessary + +2011-03-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: remove some debugging, update TODO + +2011-03-27 Marc-André Lureau <marcandre.lureau@redhat.com> + + Revert "gtk/display: remove unused mode name" + This reverts commit 33ef5a9368534f7fcb77ef60d8811ae08a707e4f. + +2011-03-23 Christophe Fergeau <cfergeau@gmail.com> + + gtk/display: be more paranoid about potentially NULL pointer + If things don't go as expected in gnome_rr_config_ensure_primary + (for example we don't find any usable output), we may end up + trying to dereference a NULL pointer. It's better to check + top_left is not NULL before using it. + + gtk: don't attempt to dereference NULL pointer + In spice_channel_handle_migrate there's an explicit check for + data being NULL. However, we subsequently dereference it twice + even when it can be NULL. Add explicit checks to avoid that. + + gtk: remove unused variables + They were spotted by the clang static analyzer. + +2011-03-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: WIN32 support resolution update + + gtk/spicy: WIN32 GTK icon theme fallback in recentmanager is buggy + + gtk/display: implement windows backend + + gtk/display: remove unused mode name + +2011-03-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/display: avoid use of g_assert, we are trying to make a library + + gtk/display: split x11/windows backend + For better or worse.. + +2011-03-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/display: start splitting display x11/windows backend + +2011-03-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/display: fix build with win32 + + TODO: update + + gtk: fix warning when building without sasl + + gtk/spicy: fix win32 build + + build: clean up some unused autoconf.ac + +2011-03-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + README: minor sasl dependency update + + gtk/channel: return if pubkey is NULL + Patch suggested by Alon Levy. + + http://lists.freedesktop.org/archives/spice-devel/2011-March/002943.html + + build: fix a copy&paste typo + + spicy: change current output resolution in fullscreen + + gtk/display: add rr_config_dump + + gtk: import display configuration from gnome-desktop + +2011-03-15 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix crash when clipboard_primary owner change + Clean up handler when destroyed. + + /usr/local/stow/virt-manager/share/virt-manager/virt-manager.py:450: Warning: g_type_instance_get_private: assertion `instance != NULL && instance->g_class != NULL' failed + gtk.main() + + Program received signal SIGSEGV, Segmentation fault. + [Switching to Thread 0x7ffff7fd4720 (LWP 19098)] + 0x00007fffe8881ab2 in get_selection_from_clipboard (d=0x0, cb=0x1df8510) + at spice-widget.c:996 + 996 if (cb == d->clipboard) { + (gdb) bt + at spice-widget.c:996 + 0x30f5750, data=0x1ea3000) at spice-widget.c:1114 + 0x0, n_param_values=2, param_values=0x1e96a90, invocation_hint= + 0x7fffffffd280) at gclosure.c:767 + detail=0, instance=0x1df8510, emission_return=0x0, instance_and_params= + 0x1e96a90) at gsignal.c:3252 + instance=<value optimized out>, signal_id=<value optimized out>, + + gtk: map-file missig test_common_capability + +2011-03-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + TODO: update + + gtk: add display width/height properties + +2011-03-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add multiple selection clipboard sharing + +2011-02-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add SASL support + +2011-02-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix spice-client-gtk-3.0.pc requires + +2011-02-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add private spice_session_get_{password,host,cert_subject}() + + gtk: add error block to spice_channel_recv_link_msg() + + gtk: add spice_channel_flush_sasl() + + gtk: add spice_channel_read_sasl() + + build: add --with-sasl build option (from gtk-vnc) + + gtk: share clipboard images + + gtk: split agent msg to VD_AGENT_MAX_DATA_SIZE if required + Fix clipboard sharing of large objects + + gtk: add spice_channel_set_common_capability() + + gtk: make it easier to debug test_capability + + gtk: s/g_get_monotonic_clock/g_get_monotonic_time + + common: add spice_channel_test_common_capability() + +2011-02-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + data: update spicy-for-windows.nsis + +2011-02-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk/spicy: add --version option + +2011-01-27 Marc-André Lureau <marcandre.lureau@redhat.com> + + release 0.5 + + gtk: fix windows build + + common: fix windows build + + gtk: fix hitting wall / real screen borders + +2011-01-26 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add "migration-state" enum to make it easier to track migrations + + gtk: when input channel is not ready, silently drop input events + +2011-01-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + common: sync with upstream + + common: spice_memdup could accept NULL + + gtk: spicy: add --host-subject argument + + gtk: move channel verification parameter to session + + gtk: rename s/spice-channel-enums/spice-glib-enums + + gtk: add pubkey verification on migration + + gtk: make use of common/ssl_verify.c + + common: add ssl_verify.c common code + + common: ring.h should include stddef for NULL usage + + gtk: add 'pubkey' and 'cert-subject' properties + +2011-01-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add channel certificate 'verify' property + + gtk: spicy: display connection dialog on TLS error + + TODO, README: update + + gtk: implement MIGRATE_CANCEL + + gtk: track switch host idle source + + gtk: add SpiceMainChannel::migration-started + With this signal, it is possible for the client to provide sockets to + a migrating session. + +2011-01-24 Tiziano Mueller <dev-zero@gentoo.org> + + Use g_free instead of free in fail codepath as well. Warn if password is provided in the uri. Free allocated unencoded uri string. + +2011-01-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: handle seamless migrations + + gtk: handle DISPLAY_RESET + + gtk: add spice_session_new_from_session() + A light copy constructor for migration. + + gtk: exit coroutine loop of a channel migrating + + gtk: add spice_channel_swap(), swap connection details + + gtk: use a callback to handle spice_channel_recv_msg() + + gtk: add channel_up() helper and SPICE_CHANNEL_STATE_MIGRATING + + gtk: use a session state on disconnection, be reentrant + + gtk: add spice_session_set_port() private API, use it + + TODO: add todo about mouse reaching borders + + gtk: order to clarify what is swapped on migration + + gtk: add private get_channel_{id,type} + +2011-01-20 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: cosmetic, make it look safer session_channel_destroy() + Although not necessary, this loop rewrite is easier to read, to see + that the function is safe: the function returns when removing the + item, so it was safe before but as well... + +2011-01-19 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix small mem-leak + + gtk: default construction value in property parameter + +2011-01-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: remove scheme parsing, and tidy up the function + + Merge commit 'refs/merge-requests/2' of git://gitorious.org/spice-gtk/spice-gtk + + gtk: support reconnection during channel loop (coroutine regression) + This is needed for protocol downgrade, and TLS switching. + +2011-01-17 Tiziano Mueller <dev-zero@gentoo.org> + + Add 'password' to recognized parameters in the uri. + + Use glib's URI parse functions to properly identify the scheme and unescape the string. + + Fixed implicitly declared toupper. + +2011-01-16 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: stay unconnected until the FD is provided by the client + +2011-01-14 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: fix distcheck + +2011-01-14 Daniel P. Berrange <berrange@redhat.com> + + Fix rendering with GTK3 + In GTK2 world there is an expose_event handler, so a choice + of the X11 or cairo backends can be used. + + In GTK3 world only the draw_event exists, which must use + cairo + + Disallow python module and X11 rendering with GTK3 + In GTK3 the python binding is provided via introspection. + The X11 rendering code is not compatible with GTK3 since + all GTK3 drawing is cairo based and there is no expose_event + any more + + Make keyboard code support multiple GDK backends + Adapt the keyboard code so that it builds with GTK2 and GTK3, + where the latter has multiple GDK backends + + Fix use of GdkDrawable to be compat with GTK3 + In GTK3, the GdkDrawable class is gone, leaving only GdkWindow. + The GdkDrawable class can be mostly avoided in Gtk2, thus + eliminating the compat problems with Gtk3. Only a couple of + compat calls need to be added to allow compilation on both. + + Adapt build system to allow building with GTK3 + The new configure flag '--with-gtk' can be used to choose + which GTK version to build against, defaulting to GTK2. + To enable GTK3 use + + ./configure --with-gtk=3.0 + + The libspice-client-glib-2.0.la library is unchanged, building + against glib-2.0 at all times. + + The GTK3 build will produce a libspice-client-gtk-3.0.la + The include files will also live in $prefix/spice-client-gtk-3.0 + and the pkgconfig is called spice-client-gtk-3.0 too. + + This allows for full parallel install of GTK2 and GTK3 builds + + Include ABI version in library names. + To allow easy parallel install of spice-gtk builds against GTK2 + and GTK3, include the ABI version in the library names. + + libspice-gtk.la -> libspice-gtk-2.0.la + libspice-glib.la -> libspice-glib-2.0.la + + The PyGtk module doesn't change because that is obsolete and + unused in GTK3 world. + +2011-01-14 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: spicy: make recent name similar to a URI without spice:// + + gtk: TLS add hostname verification + + gtk: TLS fixes: URI parsing and coroutine regression + +2011-01-13 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: spicy: add recent connexions chooser in connect dialog + + gtk: spciy: connect to selected recent item + + gtk: spicy: display recent connexions in chooser list + + data: add spice-mime, and spicy.desktop - disabled for now + + gtk: spicy: correctly unref ui/accel objects + + gtk: warn only if audio playback time is not monotonic + +2011-01-12 Marc-André Lureau <marcandre.lureau@redhat.com> + + common: add ring_get_length() for debugging purposes + + gtk: simplify debugging of coroutine-related path + + gtk: handle MIGRATE_SWITCH_HOST + +2011-01-11 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: make channel_disconnect() a vmethod + + gtk: remove useless g_object_get + + gtk: allow calling spice_main_clipboard_release() even if agent is not connected + + gtk: add some DEBUG related to migration + +2011-01-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: build x11 keyboard code with cairo backend + + build: replace echo by AC_MSG_NOTICE, that way it's logged + + build: get rid of _DEPENDENCIES and -lspice-client* + Suggested by Jürg Billeter. + +2011-01-08 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: be more careful when accessing GDK_WINDOW_XDISPLAY + +2011-01-07 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: emit ERROR_LINK when connecting to non-spice server + + gtk: fix async reading... booo, that was *really* missing + + update NEWS and TODO for v0.4 + + gtk: ignore clipboard owner signal when main channel disconnected + + gtk: simplify CHANNEL_CLOSE event handling + +2011-01-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add missing set_delay() symbol to map-file + +2011-01-04 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: help libtool/koji install client-glib before client-gtk + + gtk: fix reconnection from dialog in spicy + Closing the session while attempting a new one is a bad idea + + gtk: s/warning/message on failed connect + + build: win32: package libgstdirectsoundsrc.dll as well + + gtk: gstaudio: add recording + +2011-01-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: gstaudio: timestamp appsrc buffer to be in sync with audio sink clock + If buffer are not timestamped with the current running time, they + arrive too late. GStreamer seems to deal with some compensation of + buffer jitter, but do not correct clock time. Late buffer are late and + not heard. + +2010-12-30 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: win32: refix jpeg_boolean to build on mingw + Same fix made by Alon Levy in spice. + + Merge commit 'refs/merge-requests/1' of git://gitorious.org/spice-gtk/spice-gtk into integration + + build: win32: add spicy-for-windows.exe scripts + +2010-12-29 Tiziano Mueller <dev-zero@gentoo.org> + + jpeg_boolean is a mingw32-libjpeg specific thing. Use a define check rather than a version check. + +2010-12-29 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: win32: clean-up and GSocket quirks + +2010-12-28 Marc-André Lureau <marcandre.lureau@redhat.com> + + build: search for .defs file under $(srcdir) + +2010-12-27 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: win32: fallback to g_get_home_dir() if g_getenv() failed + + gtk: win32: channel_new() must be called in main context + + gtk: win32: create a drawing context + +2010-12-23 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: pulse: reduce playback latency to 20ms + + gtk: pulse: flush audio buffer on cork + + gtk: synchronize video on mmtime + + gtk: update mm time based on playback time+delay + +2010-12-22 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add private spice_channel_get_session() + +2010-12-22 Alon Levy <alevy@redhat.com> + + gtk: handle server sending DRAW_COPY before MARK + +2010-12-21 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: spicy use shift+f12 for grab sequence + + gtk: handle SPICE_CURSOR_FLAGS_NONE correctly + + update NEWS, fix distcheck + + gtk: improve mouse support in server mode with scaling enabled + +2010-12-20 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix cursor r/b colors being inverted + + gtk: add support for SPICE_CURSOR_TYPE_COLOR{4,16,32} + + gtk: improve 16bits color code, fix rendering glitches + + gtk: fix scaling for x11 backend + + gtk: spicy, save statusbar/toolbar display status + Fix https://bugs.freedesktop.org/show_bug.cgi?id=31991 + + gtk: fix scaling line artifacts + + gtk: add a few precondition checks, and modify debug messages + +2010-12-18 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix a dead-lock in clipboard handling + In some condition (in virt-manager but not with spicy), + g_main_loop_run() will deadlock. Use GDK_THREAD_LEAVE () like + gtk_dialog_run() code. + + Also, turn on clipboard sharing by default. + +2010-12-17 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: implement clipboard_paste_from_guest() + + gtk: correctly return empty clipboard request + + gtk: fix invalid memory access on palette cache + This fixes a valgrind error: + + GSpice-Message: display_handle_stream_create: id 49 + (lt-spicy:23948): GSpice-DEBUG: spice-channel-cache.h:107 cache_add: palette 26704 (1) + GSpice-Message: display_handle_stream_destroy: id 49 + ==23948== Invalid read of size 4 + ==23948== at 0x53C07E9: lz_plt8_to_rgb32_decompress (lz_decompress_tmpl.c:304) + ==23948== by 0x53C71FA: lz_decode (lz.c:661) + ==23948== by 0x53231AF: canvas_get_lz (canvas_base.c:834) + ==23948== by 0x5323747: canvas_get_image_internal (canvas_base.c:1109) + ==23948== by 0x5323BD0: canvas_get_image (canvas_base.c:1282) + ==23948== by 0x5325FDB: canvas_draw_copy (canvas_base.c:2196) + ==23948== by 0x531670A: display_handle_draw_copy (channel-display.c:967) + ==23948== by 0x53171B5: spice_display_handle_msg (channel-display.c:1130) + ==23948== by 0x52F3B4D: spice_channel_recv_msg (spice-channel.c:1026) + ==23948== by 0x52F3E61: spice_channel_iterate_read (spice-channel.c:1140) + ==23948== by 0x52F3F51: spice_channel_iterate (spice-channel.c:1163) + ==23948== by 0x52F44F7: spice_channel_coroutine (spice-channel.c:1272) + ==23948== Address 0x191c067c is 1,132 bytes inside a block of size 1,277 free'd + ==23948== at 0x4C27187: free (vg_replace_malloc.c:325) + ==23948== by 0x52F1D03: spice_msg_in_unref (spice-channel.c:363) + ==23948== by 0x52F3B60: spice_channel_recv_msg (spice-channel.c:1029) + ==23948== by 0x52F3E61: spice_channel_iterate_read (spice-channel.c:1140) + ==23948== by 0x52F3F51: spice_channel_iterate (spice-channel.c:1163) + ==23948== by 0x52F44F7: spice_channel_coroutine (spice-channel.c:1272) + ==23948== by 0x53CA1C9: coroutine_trampoline (coroutine_ucontext.c:52) + ==23948== by 0x53C9FBA: continuation_trampoline (continuation.c:43) + ==23948== by 0x5EED71F: ??? (in /lib64/libc-2.12.90.so) + ==23948== by 0xE7F2E7F: ??? + ==23948== + + The invalid pointer seems to come from an image palette that might not + be cached or ref'ed correctly: + + at ../common/canvas_base.c:697 + 0x7fffe45aab88) at ../common/canvas_base.c:705 + + gtk: wip gstreamer audio backend + + gtk: wip scaling support + + gtk/spicy: add scaling option + + gtk: add cairo display backend + + build: basic windows build support + + common: add windows.h where required + This patch should be sent to upstream as well.. + + common: sync with upstream + + gtk: make pulse audio backend optional + + gtk: revert 16 bits multi-monitor config + The Linux vdagent doesn't like multi-monitor configuration. + + build: add map-file in EXTRADIST + + gtk: fix 16bits expose code when black borders >0 + + gtk: fix XShm error fallback code + XDestroyImage is attempting to free(ximage->data). However, data is + owned by the display channel. + + gtk: avoid spurious set_display() calls + + gtk: add support for 16 bits + + gtk: fix video playback being distorted + + gtk: fix windows qxl rendering and warnings + Based on experimentation with spicec, it is normal to get + surface_destroy() with unknown surface id. Also, it should be + considered as an added refcount when adding an existing image/pixmap + in the cache. + +2010-12-10 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: complete API documentation + +2010-12-09 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add g_object_notify_main_context() + + gtk: continue API documentation + +2010-12-06 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: hide unwanted public symbols + + gtk: s/vnc/spice/ grab_sequence, break API + + gtk: remove old tcp.c code + + TODO: update + +2010-12-05 Marc-André Lureau <marcandre.lureau@redhat.com> + + Merge branch 'wip/coroutines' + + gtk: first stab at gtk-doc documentation + + gtk: WIP coroutines playback & record + + gtk: WIP coroutines inputs + + gtk: WIP coroutines display + + gtk: WIP coroutines cursor + + gtk: WIP coroutines main channel + + gtk: WIP handle disconnect with coroutines + + gtk: WIP tidy main_context_signal_emit() up + Add g_signal_emit_main_context() and make use of it + + gtk: WIP make coroutine loop overridable + + gtk: WIP add the support for system -> coroutine write + + gtk: WIP spice-channel documentation + + gtk: WIP enable TLS connection with coroutines + + gtk: WIP use coroutines in spice-channel + + gtk: WIP use coroutines and GSocket to connect + + gtk: add coroutine utilities + + gtk: fix an invalid clipboard memory copy + + gtk: don't grab our own guest grab + Hack? There might be a better way to do that... + + gtk: fix an invalid clipboard memory copy + + gtk: don't grab our own guest grab + Hack? There might be a better way to do that... + + build: add .gitignore + + gtk: SPICE_DEBUG glz_decoder_window_resize message + +2010-12-03 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: fix crash when spicy configuration is empty + + gtk: fix crash when spicy configuration is empty + + gtk: remove invalid properties warning in spicy + + build: spice-protocol >= 0.6.3 required + + gtk: remove invalid properties warning in spicy + + build: spice-protocol >= 0.6.3 required + +2010-12-02 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: visibility option for statusbar/toolbar in spicy + + gtk: delay PA stream creation when context is ready + +2010-12-01 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: don't uncork new streams + + gtk: save/restore spicy configuration + Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=31991 + + gtk: add CELT recording + + gtk: add CELT playback + +2010-11-30 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add {session,channel}_open_fd() + +2010-11-29 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add channel.set_capability() + + gtk: put some g_message() under SPICE_DEBUG + + TODO: update + + gtk: add clipboard sharing for text + + gtk: add dispay config + +2010-11-26 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: progressive agent message recomposition + + gtk: add jpeg decoder + +2010-11-25 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add zlib decoder + + build: fix make -j + + build: re-enable -Wflags, and fix a few warnings + + build: use git-version-gen + + README: add a few missing dependencies + + gtk: disconnect record stream when record_stop() + This behaviour is different than playback. The main difference is that + a playback stream will stay active, while the recording stream will be + removed: that way the GNOME volume control can notice the user there + is no active recording, by hiding the microphone icon. + + Playback is more frequent (sounds events...) and it would be + unfriendly if the stream was removed/added every now and then from the + volume control list. + + build: update build depedencies + + build: update README + + po: add fr translation + + gtk: mark spice-cmdline strings as translatable + + gtk: make snappy translatable + + gtk: remove spice prefix in default signal handler + + gtk: add raw audio recording + +2010-11-24 Marc-André Lureau <marcandre.lureau@redhat.com> + + gtk: add channel_test_capability() + + gtk: add save mm_time in session + + add AUTHORS & TODO + + i18: add basic support - mark translatable spicy strings + + gtk: read remote caps + + gtk: add a couple of new TODO + + gtk: handle agent token + + gtk: add SPICE_MSG_DISCONNECTING handler + + gtk: don't send inputs before the channel is ready, or else it will eof + + gtk: expose Audio object in python + + gtk: fix MainChannel python bindings + + gtk: ensure we sync key locks after connection + + gtk: move audio stuff in client-glib + + gtk: fix make distcheck + + gtk: fix out of dir build + + gtk: add missing copyright headers + + README: move from gtk/ to / + + build: install gtk and glib headers in different dirs + And various improvements + + gtk: current code is blocking - remove O_NONBLOCK + + gtk: add padding on common base classes: channe/session/widget + + gtk: send the channel caps + + gtk: uncomment some agent string-msg table entries + I don't know why it was commented. + + gtk: sync keyboard lock (X11 only) + + gtk: release keys on disconnect + + gtk: fix getpixbuf colorspace + + gtk: make spice_session_disconnect() reentrant + + gtk: a channel own a ref on a session + This fix calling session_disconnect() in a main_channel_event() callback for instance. + + gtk: add a couple of warning on invalid arguments in public methods + + gtk: use sane default values for spice_audio_new() + + gtk: passing seems wrong, it should be the context + + gtk: adapted to be a working C library + + gtk: handle display-mark + + gtk: hack to handle scrolling + + gtk: implement cursor_reset and plug a memleak + + build: fix a few warnings reported by clang + + gtk: add a flag to turn debug off, SPICE_DEBUG=1 to override + + gtk: don't dereference NULL pointers in destroy + On some error conditions, that happens. + + gtk: add get_pixbuf() for 8/8/8 surfaces + + gtk: add display_send_keys() again, adapted from gtk-vnc.. + + gtk: signal keybard-grab status + Perhaps we should have grab/ungrab signals, instead of an int... + + gtk: add support fro grab keys, based on gtk-vnc code + + gtk: track when mouse/keyboard grab fail + Avoid sending mouse-grab true if the grab failed. + + gtk: python module, register enums + + gtk: untabify + + gtk: use SPICE_DEBUG_CURSOR=1 for debugging + + gtk: allow key repeatition + + gtk: get rid of the remaining assert() + + gtk: make more build silent + + gtk: python module - add manualy defined bindings + + gtk: fix a few gcc warnings + + gtk: add pygtk module + + gtk: remove spice_channel_id() function + The value can be retrieved by property + + gtk: remove spice- prefix in signal name + + gtk: remove spice-event + The abstraction was not really useful, a bit buggy, and a bit more restrictive + + gtk: get rid of asserts, they are not good in libraries + + gtk: use g_log functions instead of fprintf and custom handler + + gtk: make spice_msg_out private + + gtk: GObject Introspection support + +2010-11-23 Gerd Hoffmann <kraxel@redhat.com> + + fix channel cleanup (unbreaks tls) + + spicy: quit on connect failure + + cursor tweaks + + widget: server mouse fixups. + + spicy: use uri for recent entries. + + session: add uri property. + + sound: add recording [not finished yet] + + display: release cursors + + drop+improve debug messages. make protocol a session not a channel property. + + handle partial link message reads + + display: release streams + + display: release glz window bits + + display: release surfaces + + display: release cached palettes and images + + move resize timer from widget to display channel + + more object destruction fixes + + misc object destruction fixes + + spicy cleanup fixes + + display: move IPC_RMID to avoid shm leaking + + spicy: allocate all state storage + + inputs fixups + + spicy: use modifier signal, improve status line. + + inputs: add modifier signal. + + stream regions + + spicy: use grab-mouse signal, set initial kbd focus + + spice widget: some agent bits, add mouse-grab signal + + some more agent bits + + main channel signal fixup. + + auit when the connect dialog is canceled. + + handle VD_AGENT_ANNOUNCE_CAPABILITIES + + mouse and agent interface tweaks. + + connect dialog windup + + spicy: started working on a fancy connect dialog. + + switch snappy to glib command line parsing, factor out common spice options. + + make option menu more verbose + + switch spicy to glib command line parsing + + add audio init wrapper, move pulse bits into gtk lib. + + make spice_session_get_channels return a glist + + rename spice_msg get/put functions to ref/unref + + more clipboard bits + + early cut+paste bits + + zap sub-message debug printfs + + display: handle inval-list message, fix image cacheing. + + spice-channel: Handle incoming sub messages. + + Add glib objects + gtk widgets for spice. + +2010-11-23 Marc-André Lureau <marcandre.lureau@gmail.com> + + Initial import from SPICE diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..47cf840 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,113 @@ +ACLOCAL_AMFLAGS = -I m4 +NULL = + +SUBDIRS = spice-common src man po doc data + +if BUILD_TESTS +SUBDIRS += tests +endif + +if HAVE_INTROSPECTION +if WITH_VALA +SUBDIRS += vapi +endif +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = \ + spice-client-glib-2.0.pc \ + $(NULL) + +if WITH_GTK +pkgconfig_DATA += spice-client-gtk-3.0.pc +endif + +if WITH_CONTROLLER +pkgconfig_DATA += spice-controller.pc +endif + +INTLTOOL_FILES = \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in \ + $(NULL) + +DISTCLEANFILES = \ + $(pkgconfig_DATA) \ + intltool-extract \ + intltool-merge \ + intltool-update \ + gnome-doc-utils.make \ + po/.intltool-merge-cache \ + $(NULL) + +EXTRA_DIST = \ + build-aux/git-version-gen \ + gtk-doc.make \ + .version \ + $(INTLTOOL_FILES) \ + $(NULL) + +MAINTAINERCLEANFILES = \ + ABOUT-NLS \ + aclocal.m4 \ + config.h.in \ + m4/gtk-doc.m4 \ + m4/intltool.m4 \ + m4/libtool.m4 \ + m4/ltoptions.m4 \ + m4/ltsugar.m4 \ + m4/ltversion.m4 \ + m4/lt~obsolete.m4 \ + build-aux/ar-lib \ + build-aux/compile \ + build-aux/config.guess \ + build-aux/config.rpath \ + build-aux/config.sub \ + build-aux/depcomp \ + build-aux/install-sh \ + build-aux/ltmain.sh \ + build-aux/missing \ + build-aux/mkinstalldirs \ + build-aux/test-driver \ + po/Makefile.in.in \ + gtk-doc.make \ + $(NULL) + +# Generate the ChangeLog file +# and insert it into the directory we're about to use to create a tarball. +.PHONY: gen-ChangeLog gen-THANKS +gen-ChangeLog: + if test -d .git || test -d ../.git; then \ + $(top_srcdir)/build-aux/gitlog-to-changelog > $(distdir)/cl-t; \ + rm -f $(distdir)/ChangeLog; \ + mv $(distdir)/cl-t $(distdir)/ChangeLog; \ + fi + +# see git-version-gen +dist-hook: gen-ChangeLog gen-THANKS + echo $(VERSION) > $(distdir)/.tarball-version + +BUILT_SOURCES = $(top_srcdir)/.version +$(top_srcdir)/.version: + echo $(VERSION) > $@-t && mv $@-t $@ + +DISTCHECK_CONFIGURE_FLAGS = \ + --enable-introspection \ + --disable-vala \ + --disable-usbredir \ + --enable-gtk-doc \ + --enable-werror \ + --with-gtk=3.0 \ + $(NULL) + +gen-THANKS: + $(AM_V_GEN)if test -d .git || test -d ../.git; then \ + echo "The spice-gtk team would like to thank the following contributors:" > $(distdir)/t-t; \ + echo >> $(distdir)/t-t; \ + git log --format='%aN <%aE>' | sort -u >> $(distdir)/t-t; \ + rm -f $(distdir)/THANKS; \ + mv $(distdir)/t-t $(distdir)/THANKS; \ + fi + +-include $(top_srcdir)/git.mk diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..0f9f527 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1110 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_TESTS_TRUE@am__append_1 = tests +@HAVE_INTROSPECTION_TRUE@@WITH_VALA_TRUE@am__append_2 = vapi +@WITH_GTK_TRUE@am__append_3 = spice-client-gtk-3.0.pc +@WITH_CONTROLLER_TRUE@am__append_4 = spice-controller.pc +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = spice-client-glib-2.0.pc spice-client-gtk-3.0.pc \ + spice-controller.pc +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = spice-common src man po doc data tests vapi +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/spice-client-glib-2.0.pc.in \ + $(srcdir)/spice-client-gtk-3.0.pc.in \ + $(srcdir)/spice-controller.pc.in \ + $(top_srcdir)/build-aux/ar-lib $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing AUTHORS COPYING NEWS README \ + TODO build-aux/ar-lib build-aux/compile build-aux/config.guess \ + build-aux/config.sub build-aux/install-sh build-aux/ltmain.sh \ + build-aux/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 +GZIP_ENV = --best +DIST_TARGETS = dist-bzip2 dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 +NULL = +SUBDIRS = spice-common src man po doc data $(am__append_1) \ + $(am__append_2) +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = spice-client-glib-2.0.pc $(NULL) $(am__append_3) \ + $(am__append_4) +INTLTOOL_FILES = \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in \ + $(NULL) + +DISTCLEANFILES = \ + $(pkgconfig_DATA) \ + intltool-extract \ + intltool-merge \ + intltool-update \ + gnome-doc-utils.make \ + po/.intltool-merge-cache \ + $(NULL) + +EXTRA_DIST = \ + build-aux/git-version-gen \ + gtk-doc.make \ + .version \ + $(INTLTOOL_FILES) \ + $(NULL) + +MAINTAINERCLEANFILES = \ + ABOUT-NLS \ + aclocal.m4 \ + config.h.in \ + m4/gtk-doc.m4 \ + m4/intltool.m4 \ + m4/libtool.m4 \ + m4/ltoptions.m4 \ + m4/ltsugar.m4 \ + m4/ltversion.m4 \ + m4/lt~obsolete.m4 \ + build-aux/ar-lib \ + build-aux/compile \ + build-aux/config.guess \ + build-aux/config.rpath \ + build-aux/config.sub \ + build-aux/depcomp \ + build-aux/install-sh \ + build-aux/ltmain.sh \ + build-aux/missing \ + build-aux/mkinstalldirs \ + build-aux/test-driver \ + po/Makefile.in.in \ + gtk-doc.make \ + $(NULL) + +BUILT_SOURCES = $(top_srcdir)/.version +DISTCHECK_CONFIGURE_FLAGS = \ + --enable-introspection \ + --disable-vala \ + --disable-usbredir \ + --enable-gtk-doc \ + --enable-werror \ + --with-gtk=3.0 \ + $(NULL) + +all: $(BUILT_SOURCES) config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +spice-client-glib-2.0.pc: $(top_builddir)/config.status $(srcdir)/spice-client-glib-2.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +spice-client-gtk-3.0.pc: $(top_builddir)/config.status $(srcdir)/spice-client-gtk-3.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +spice-controller.pc: $(top_builddir)/config.status $(srcdir)/spice-controller.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ + dist-tarZ dist-xz dist-zip distcheck distclean \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Generate the ChangeLog file +# and insert it into the directory we're about to use to create a tarball. +.PHONY: gen-ChangeLog gen-THANKS +gen-ChangeLog: + if test -d .git || test -d ../.git; then \ + $(top_srcdir)/build-aux/gitlog-to-changelog > $(distdir)/cl-t; \ + rm -f $(distdir)/ChangeLog; \ + mv $(distdir)/cl-t $(distdir)/ChangeLog; \ + fi + +# see git-version-gen +dist-hook: gen-ChangeLog gen-THANKS + echo $(VERSION) > $(distdir)/.tarball-version +$(top_srcdir)/.version: + echo $(VERSION) > $@-t && mv $@-t $@ + +gen-THANKS: + $(AM_V_GEN)if test -d .git || test -d ../.git; then \ + echo "The spice-gtk team would like to thank the following contributors:" > $(distdir)/t-t; \ + echo >> $(distdir)/t-t; \ + git log --format='%aN <%aE>' | sort -u >> $(distdir)/t-t; \ + rm -f $(distdir)/THANKS; \ + mv $(distdir)/t-t $(distdir)/THANKS; \ + fi + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..178bedd --- /dev/null +++ b/NEWS @@ -0,0 +1,414 @@ +v0.32 +===== + +libspice-client-gtk API/ABI break: library soname/version has been +bumped, and deprecated symbols have been removed. In practice, most +of the API (in particular for language bindings) should be unchanged. + +- drop gtk+ 2.0 support +- require gtk+ >= 3.12 and glib >= 2.36 +- add GStreamer as a backend for mjpeg, vp8 & h264 decoding + This allows the upcoming Spice server release to send video + regions with better codecs. +- a number of spice-gtk structures are now private +- spice-gtk widget is no longer a GtkDrawingArea but an opaque type + with only guarantee to be a GtkWidget +- virgl: use GtkGlArea if possible (on wayland only atm) +- virgl: various fixes (multiple display, resize, canvas-less support) +- win-usbredir: use UsbDk backend when available and various + improvements +- ensure that dnd file copy get cancelled +- some JP and KR keyboard handling fixes on Windows +- fix SASL GSSAPI +- fix ipv6 proxy address handling +- allow smaller widget with scaling enabled +- add spice_main_request_mouse_mode() to request mouse mode +- add SpiceGtkSession:sync-modifiers to change modifiers sync behaviour +- various video decoding improvements +- use GTask instead of GSimpleAsyncResult +- misc bindings, leaks, warnings, and spelling fixes + +v0.31 +===== + +- NOTE: this is the last release to support gtk+ 2.0 +- add local GL scanout support for virtio-gpu/virgl guests +- new file-transfer API, to be able to monitor transfers etc +- new spice_display_change_preferred_compression() API +- better authentication error reports +- usbredir: drop isoc packets on low bandwidth (rhbz#1264156) +- usbredir: add counter of free channels (rhbz#1298772) +- add a toplevel include header spice-client-gtk.h +- grab keyboard based on session focus (rhbz#1275231) +- don't print error message on successful file transfer (rhbz#1265562) +- allow simultaneous support for Pulse and GStreamer audio +- remove GSlice usage +- some BE endianness fixes +- misc leak and use after-free fixes +- documentation fixes + +v0.30 +===== +- spice-protocol is no longer bundled with spice-gtk. Requires + spice-protocol >= 0.12.10 +- Handle single headed monitors that have a non-zero x, y config +- various small improvements to 'spicy' test application +- Fix build with automake < 1.13 +- various bug fixes and improvements +- New API: + - spice_main_update_display_enabled() + - Add SpiceSession::preferred-compression property and + --spice-preferred-compression commandline switch (requires a + yet-to-be-released version of spice server) +- ability to set the SpiceDisplay::keypress-delay property via a new + SPICE_KEYPRESS_DELAY environment variable + +v0.29 +===== + +- sync guest audio volume with client volume +- use stream volume for PulseAudio source +- on Windows, fail early during initialization if the usbclerk service + can't be reached +- fix audio and usb managers to work with client provided fds +- many crasher and bug fixes + +v0.28 +===== + +- webdav improvements: + - no longer spawn a server thread + - no longer use local TCP sockets & port + - provides read-only mode with SpiceSession:share-dir-ro + - requires libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91 +- drop gstreamer 0.10 in favour of 1.0 +- add spice+unix://path connection support +- accept URI with empty parameters value, + such as spice://localhost?port=5900&tls-port= +- fixed lz4 support +- silence some harmless warnings +- misc API documentation improvements +- switch-host migration fixes +- learn to build --without-gtk +- bugs and regressions fixes + +v0.27 +===== + +- add GStreamer 1.0 audio support +- add LZ4 compression algorithm support +- learn to release the keyboard grab on release keys pressed (ctrl+alt + by default), to let alt+f4/alt-tab and others for client side +- session and channels life-cycle changes: a channel will no longer + hold a reference after session disconnection +- migration fixes, fail early on client provided fds (this is left to + solve in the future) +- fix support for Gtk+ 3.0 on Windows +- clipboard size fixes +- server-side pointer drawing on grab +- new APIs: + spice_usb_device_get_libusb_device() + spice_session_is_for_migration() +- build-sys improvements + +v0.26 +===== + +- allow transferring multiple files at once with dnd +- avoid guest-side fd leak when transferring empty files + with dnd +- add support for passing a username with SASL authentication +- hide guest cursor when ungrabbing mouse in server mode +- make sure client cursor is in the same position as the guest cursor when + ungrabbing mouse in server mode +- add man page for command line options of application using spice-gtk +- strip '\0' from text clipboard data +- fix synchronization of keyboard modifiers +- coroutine improvements +- use http by default when SPICE_PROXY uri has no scheme + +v0.25 +===== + +- Fix SPICE_GTK_MICRO_VERSION define for default value +- Make "phodav", the webdav server, an external dependency rather than + a submodule + +v0.24 +===== + +- support folder sharing, via WebDAV channel +- add HTTPS proxy support (requires glib 2.28), and Basic auth +- add SPICE_GTK_CHECK_VERSION macro +- advertise SASL capability early (to help fips-enabled servers) +- fix crash when releasing primary surface +- fix a few memory leaks with SASL +- fix spice_display_get_pixbuf() with offset area +- build-sys improvements + +- note: until now, providing an invalid plain-port didn't error, and + was falling back silently on tls-port. With this release, an error + will be reported if the port can't be opened. + +v0.23 +===== + +- support Opus codec for audio channels +- ssl: use tls 1.0 or better +- support gdbus instead of dbus-glib when available +- misc build-sys, compile and runtime fixes + +v0.22 +===== + +- improve inverted cursor support +- use system-wide trust certificate store +- make sasl support work with other method than MD5 +- fix some clipboard crasher, limit clipboard size +- fix various regressions: + usbredir, alt-tab on win32, palette crash, agent notification, old + protocol support, sasl ending crash, gthread coroutine crash, close + sockets on migration, pulse backend crash +- fix a few memory leaks +- build-sys improvements + +v0.21 +===== + +- improve inverted cursor support +- win32 usb redirected device uninstall fix +- add support for libusb hotplug API +- smartcard initialization fixes +- c&p converts line-endings if necessary +- rendering and overall performance improvements +- build and bindings fixes + +v0.20 +===== + +- adaptive video streaming support (sync with PulseAudio backend only) +- add spice_usb_device_manager_get_devices_with_filter() +- add --spice-secure-channels to explicitely specify secure channels +- multi-monitor, win32, USB redir fixes +- add basic gtk+ wayland and broadway backend support +- removed the GnomeRR code + +v0.19 +===== + +This is a bugfix only release, except the snappy name change +- snappy has been renamed to spicy-screenshot +- Several file-xfer fixes and improvements +- Many win32 and USB redirection related fixes +- Compile and work again with RHEL6 and older glib releases +- misc fixes and improvements + +v0.18 +===== + +- Build fix with Gtk+ unstable. +- MinGW build fixes with old headers +- Fix USB coldplug race +- Fixes rhbz#908057 + +v0.17 +===== + +- Update spice-common with fedora 875348, 826036 fixes +- Multi-monitor fixes (avoid monitor order shuffling, fix mouse offset + if monitor 0 is not at +0+0 and let agent do monitor offset) +- Add support for VD_AGENT_CAP_SPARSE_MONITORS_CONFIG +- Add controller & session "proxy" properties +- Add drag and drop file copy support to send file to guest, you will + need capable agent to use that feature. Adds spice_main_file_copy_async() +- Introspection fixes +- Build fixes + +v0.16 +===== + +- Fix crash with SSL connection (#890464) +- Send monitor config to the agent on spice_main_set_display_enabled() (#881072) +- Fix channel leak and wrong condition in spice_channel_flush() +- Build fixes + +v0.15 +===== + +- Add HTTP Proxy support (only with glib >= 2.26) +- Add "port" channel support, to allow arbitrary communication on top + of spice connection +- usb-redir: fix migration support +- win32: various keyboard & mouse fixes +- Add info message when USB dialog is empty +- Fix initial black screen on some 16bits guest +- Various bug fixes and improvements + +v0.14 +===== + +- Support for seamless migration +- Improve scaling handling, add downscale-only property to give more + control over scaling +- Better handle key press/release events in high-latency situations, + this should avoid unwanted key repetitions +- Improve unescaping in URI parsing +- Fix symbol versioning which was broken in 0.13 +- Fix for CVE-2012-4425 +- Various bug fixes and improvements + +v0.13 +===== + +- ABI break! SONAME has been bumped, all programs and libraries + linking to spice-gtk need to be recompiled against this version +- Add support for USB device redirection on Windows +- Add monitors config support (multiple monitors in same display) +- Inhibit automount on GNOME desktop, to ease USB redirection +- Better video support (reduce some glitches) +- Misc migration fixes +- Various bug fixes and improvements + +v0.12 +===== + +- Fix memory leak when guest is resized +- Fix color-depth setting +- Hide/Show cursor correctly when needed +- Fix blue-tinted video with old Spice servers +- Correct scroll-event not received with recent Gtk+ +- Fix various migrations issues +- Allow to disable CELT encoding at runtime with SPICE_DISABLE_CELT +- Various crash fixes (on pubkey, recording, clipboard) +- Build changes (common submodule) and fixes + +v0.11 +===== + +- Fix semi-seamless migration regression +- Add Spice session UUID and name support +- Add foreign menu support to controller library +- Add a simple controller testing tool spice-controller-dump +- Build fixes + +v0.10 +===== + +- USB redir is now aware of host/guest side filtering +- you can query spice_usb_device_manager_can_redirect_device() +- fix the usbredir channel lifetime to be equal to session lifetime +- set keepalive on channel socket +- fix hangs on windows when using ssl chanels +- add a SpiceDisplay::zoom-level to maintain a scaling ratio +- add controller ENABLE_SMARTCARD option +- remove a few warnings, ui improvements, build fixes + +v0.9 +==== + +- Add command line options for setting the cache size and the glz window size +- Add a USB device selection widget to libspice-client-gtk +- Various bug fixes and code improvements + +v0.8 +==== + +- add USB redirection support, see Hans comments in the log and that + post for details: http://hansdegoede.livejournal.com/11084.html +- introduce SpiceGtkSession to deal with session-wide Gtk events, such + as clipboard, instead of doing it per display +- many cursor and keyboard handling improvements +- handle the new "semi-seamless" migration +- support new Spice mini-headers +- better coroutines: fibers on windows & jmp on linux +- add Vala vapi bindings generation +- many bug fixes and code improvements + +v0.7 +==== + +- smartcard support +- better video playback performance (jpeg-turbo & audio improvements) +- support for audio volume (needs qemu support) +- controller support for Windows (NamedPipe) +- make perl-Text-CSV optional for tarball builds +- new spice_get_option_group()/spice_set_session_option() +- keyboard improvements, grab-sequence can be configured, various windows fixes +- new tool spicy-stats, to collect informations during a session +- bugfixes: memleak fixes, SASL fixes, crash with virt-manager +- various build fixes, should build on MacOS as well now + +v0.6 +==== + +- multi-head is working now! +- change client resolution if guest can't +- support sharing large clipboard, and images +- multiple clibpoard selection +- support SASL authentication +- add experimental/unstable controller API +- and a bunch of various smaller fixes + +v0.5 +==== + +- Compatibility with gtk2 and gtk3 +- Migrations: seamless and switch host methods +- SSL verification: public key, subject and host checks added +- spice:// url parsing learned "password" argument +- spicy: recent connexions UI added +- various minor fixes + +v0.4 +==== + +- sync video with pulseaudio backend +- build with mingw, and run on Windows +- various minor fixes + +v0.3 +==== + +- fix Windows QXL driver support +- fully asynchronous operations using coroutines + (thanks go to gtk-vnc devs) +- cairo display (old XShm display can be enabled with --with-x11) +- scaling support for cairo display +- experimental audio support using GStreamer +- API reference gtk-doc +- more cursor type support +- various fixes and cleanup + +v0.2 +==== + +- gtk: disconnect record stream when record_stop() +- README: add a few missing dependencies +- build: use git-version-gen +- build: re-enable -Wflags, and fix a few warnings +- build: fix make -j +- gtk: add zlib decoder +- gtk: add jpeg decoder +- gtk: progressive agent message recomposition +- gtk: add dispay config +- gtk: add clipboard sharing for text +- TODO: update +- gtk: put some g_message() under SPICE_DEBUG +- gtk: add channel.set_capability() +- gtk: add {session,channel}_open_fd() +- gtk: add CELT playback +- gtk: add CELT recording +- gtk: save/restore spicy configuration +- gtk: don't uncork new streams +- gtk: delay PA stream creation when context is ready +- gtk: visibility option for statusbar/toolbar in spicy + +v0.1.0 +====== + +- desktop display, using GLZ compression +- audio playback/recording with PulseAudio +- video in mjpeg +- python and gobject-introspection modules +- spicy: a simple Gtk client +- snappy: a command line screenshot tool diff --git a/README b/README new file mode 100644 index 0000000..43ee08a --- /dev/null +++ b/README @@ -0,0 +1,56 @@ +spice-gtk +========= + +A Gtk client and libraries for SPICE remote desktop servers. + +Please report bugs at: spice-devel@lists.freedesktop.org + +Project content +--------------- + +libspice-client-glib-2.0 + provides glib objects for spice protocol decoding and surface rendering. + * SpiceSession (see spice-session.h). + * SpiceChannel (see spice-channel.h). + * SpiceAudio (see spice-audio.h). + * Various Spice<Type>Channel (see channel-<type>.h). + +libspice-client-gtk-3.0 + provides gtk widget to show spice display and accept user input. + * SpiceDisplay (see spice-widget.h) + +spicy + a gtk test client. The recommended client for end user is + virt-viewer (http://git.fedorahosted.org/cgit/virt-viewer.git/) + +spicy-screenshot + Command line tool, connects to spice server and writes out a + screen shot. + +spicy-stats + Command line tool, connects to spice server and writes out a + summary of connection details, amount of bytes transferred... + +SpiceClientGlib and SpiceClientGtk GObject-introspection modules. + +Build dependencies: +------------------ + +. On Fedora use: + +dnf builddep spice-gtk + +. or install: + +gtk3-devel spice-protocol intltool +openssl-devel pulseaudio-libs-devel pixman-devel +gobject-introspection-devel libjpeg-turbo-devel zlib-devel +cyrus-sasl-devel gtk-doc + +. The GStreamer backend needs: + +gstreamer1-devel gstreamer1-plugins-base-devel gstreamer1-plugins-good gstreamer1-plugins-bad-free + +. If you build from git, you'll also need: + +libtool automake vala vala-tools perl-Text-CSV diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..50d18d9 --- /dev/null +++ b/THANKS @@ -0,0 +1,54 @@ +The spice-gtk team would like to thank the following contributors: + +Alexander Bokovoy <abokovoy@redhat.com> +Alexander Larsson <alexl@redhat.com> +Alexandru Visarion <viorel.visarion@gmail.com> +Alex Efros <powerman-asdf@yandex.ru> +Alon Levy <alevy@redhat.com> +Andrew Hughes <gnu.andrew@redhat.com> +Arnon Gilboa <agilboa@redhat.com> +Attila Sukosd <attila.sukosd@gmail.com> +Benjamin Gilbert <bgilbert@cs.cmu.edu> +Christophe Fergeau <cfergeau@redhat.com> +Cody Chan <int64ago@gmail.com> +Cole Robinson <crobinso@redhat.com> +Colin Walters <walters@verbum.org> +Daniel P. Berrange <berrange@redhat.com> +David Jaša <djasa@redhat.com> +Dietmar Maurer <dietmar@proxmox.com> +Dmitry Fleytman <dmitry@daynix.com> +Dunrong Huang <riegamaths@gmail.com> +Fabiano Fidêncio <fidencio@redhat.com> +Francois Gouget <fgouget@codeweavers.com> +Frédéric Péters <fpeters@0d.be> +Frediano Ziglio <fziglio@redhat.com> +Gerd Hoffmann <kraxel@redhat.com> +Hans de Goede <hdegoede@redhat.com> +Ignacio Casal Quinteiro <icq@gnome.org> +Jani Välimaa <wally@mageia.org> +Jasper Lievisse Adriaanse <jasper@humppa.nl> +Javier Celaya <javier.celaya@flexvdi.com> +Jay.han <ezzzehxx@gmail.com> +Jeremy White <jwhite@codeweavers.com> +Jonathon Jongsma <jjongsma@redhat.com> +Kirill Moizik <kmoizik@redhat.com> +Lukas Venhoda <lvenhoda@redhat.com> +Marc-André Lureau <marcandre.lureau@redhat.com> +Marek Kasik <mkasik@redhat.com> +Matthias Clasen <mclasen@redhat.com> +Mattias Grönlund <mattias@gronlund.se> +Michael Chudobiak <mjc@avtechpulse.com> +Natanael Copa <ncopa@alpinelinux.org> +Nicolas Prochazka <prochazka.nicolas@gmail.com> +Pavel Grunt <pgrunt@redhat.com> +Ryan Lortie <desrt@desrt.ca> +Sandy Stutsman <sstutsma@redhat.com> +Snir Sheriber <ssheribe@redhat.com> +Søren Sandmann Pedersen <ssp@redhat.com> +Takao Fujiwara <tfujiwar@redhat.com> +Tiziano Müller <tiziano.mueller@stepping-stone.ch> +Uri Lublin <uril@redhat.com> +Victor Toso <victortoso@redhat.com> +Visarion-Mingopol Alexandru <viorel.visarion@gmail.com> +Yonit Halperin <yhalperi@redhat.com> +Zeeshan Ali (Khattak) <zeeshanak@gnome.org> diff --git a/TODO b/TODO new file mode 100644 index 0000000..8463c90 --- /dev/null +++ b/TODO @@ -0,0 +1,5 @@ +* implement migration support with client fd + +See list of open upstream bugs: + +https://bugs.freedesktop.org/buglist.cgi?product=Spice&component=spice-gtk&resolution=---&list_id=281013 diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..85df620 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,2140 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 1995-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2003,2004 Red Hat, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995, 1996 +# +# Modified to never use included libintl. +# Owen Taylor <otaylor@redhat.com>, 12/15/1998 +# +# Major rework to remove unused code +# Owen Taylor <otaylor@redhat.com>, 12/11/2002 +# +# Added better handling of ALL_LINGUAS from GNU gettext version +# written by Bruno Haible, Owen Taylor <otaylor.redhat.com> 5/30/3002 +# +# Modified to require ngettext +# Matthias Clasen <mclasen@redhat.com> 08/06/2004 +# +# We need this here as well, since someone might use autoconf-2.5x +# to configure GLib then an older version to configure a package +# using AM_GLIB_GNU_GETTEXT +AC_PREREQ(2.53) + +dnl +dnl We go to great lengths to make sure that aclocal won't +dnl try to pull in the installed version of these macros +dnl when running aclocal in the glib directory. +dnl +m4_copy([AC_DEFUN],[glib_DEFUN]) +m4_copy([AC_REQUIRE],[glib_REQUIRE]) +dnl +dnl At the end, if we're not within glib, we'll define the public +dnl definitions in terms of our private definitions. +dnl + +# GLIB_LC_MESSAGES +#-------------------- +glib_DEFUN([GLIB_LC_MESSAGES], + [AC_CHECK_HEADERS([locale.h]) + if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your <locale.h> file defines LC_MESSAGES.]) + fi + fi]) + +# GLIB_PATH_PROG_WITH_TEST +#---------------------------- +dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], +[# 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. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + 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 +]) + +# GLIB_WITH_NLS +#----------------- +glib_DEFUN([GLIB_WITH_NLS], + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + AC_CHECK_HEADER(libintl.h, + [gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, + [AC_TRY_LINK([ +#include <libintl.h> +], + [return !ngettext ("","", 1)], + gt_cv_func_ngettext_libc=yes, + gt_cv_func_ngettext_libc=no) + ]) + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([ +#include <libintl.h> +], + [return !dgettext ("","")], + gt_cv_func_dgettext_libc=yes, + gt_cv_func_dgettext_libc=no) + ]) + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CHECK_FUNCS(bind_textdomain_codeset) + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes)])]) + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + AC_MSG_CHECKING([if -liconv is needed to use gettext]) + AC_MSG_RESULT([]) + AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dcgettext, + [gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv], + :,-liconv)], + :,-liconv) + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + AC_CHECK_FUNCS(bind_textdomain_codeset) + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + AC_CHECK_FUNCS(dcgettext) + MSGFMT_OPTS= + AC_MSG_CHECKING([if msgfmt accepts -c]) + GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test <foo@bar.xx>\n" +"Language-Team: C <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) + AC_SUBST(MSGFMT_OPTS) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share and + dnl and CATOBJEXT=.gmo in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + ;; + *-*-openbsd*) + CATOBJEXT=.mo + DATADIRNAME=share + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac]) + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + ]) + + if test "$gt_cv_have_gettext" = "yes" ; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is not GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.ac. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLLIBS) + AC_SUBST(PO_IN_DATADIR_TRUE) + AC_SUBST(PO_IN_DATADIR_FALSE) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +# AM_GLIB_GNU_GETTEXT +# ------------------- +# Do checks necessary for use of gettext. If a suitable implementation +# of gettext is found in either in libintl or in the C library, +# it will set INTLLIBS to the libraries needed for use of gettext +# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable +# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() +# on various variables needed by the Makefile.in.in installed by +# glib-gettextize. +dnl +AU_DEFUN([GLIB_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_CC])dnl + + GLIB_LC_MESSAGES + GLIB_WITH_NLS + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; 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 + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + 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 is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ], + [[$0: This macro is deprecated. You should use upstream gettext instead.]]) + +# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) +# ------------------------------- +# Define VARIABLE to the location where catalog files will +# be installed by po/Makefile. +glib_DEFUN([GLIB_DEFINE_LOCALEDIR], +[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl +glib_save_prefix="$prefix" +glib_save_exec_prefix="$exec_prefix" +glib_save_datarootdir="$datarootdir" +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +datarootdir=`eval echo "${datarootdir}"` +if test "x$CATOBJEXT" = "x.mo" ; then + localedir=`eval echo "${libdir}/locale"` +else + localedir=`eval echo "${datadir}/locale"` +fi +prefix="$glib_save_prefix" +exec_prefix="$glib_save_exec_prefix" +datarootdir="$glib_save_datarootdir" +AC_DEFINE_UNQUOTED($1, "$localedir", + [Define the location where the catalogs will be installed]) +]) + +dnl +dnl Now the definitions that aclocal will find +dnl +ifdef(glib_configure_ac,[],[ +AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) +AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) +])dnl + +# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) +# +# Create a temporary file with TEST-FILE as its contents and pass the +# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with +# 0 and perform ACTION-IF-FAIL for any other exit status. +AC_DEFUN([GLIB_RUN_PROG], +[cat >conftest.foo <<_ACEOF +$2 +_ACEOF +if AC_RUN_LOG([$1 conftest.foo]); then + m4_ifval([$3], [$3], [:]) +m4_ifvaln([$4], [else $4])dnl +echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD +sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD +fi]) + + +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + dnl Canonicalize enable_introspection + enable_introspection=$found_introspection + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) + +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016 Free Software +dnl 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 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 is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 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]) +]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_AR([ACT-IF-FAIL]) +# ------------------------- +# Try to determine the archiver interface, and trigger the ar-lib wrapper +# if it is needed. If the detection of archiver interface fails, run +# ACT-IF-FAIL (default is to abort configure with a proper error message). +AC_DEFUN([AM_PROG_AR], +[AC_BEFORE([$0], [LT_INIT])dnl +AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([ar-lib])dnl +AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) +: ${AR=ar} + +AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], + [AC_LANG_PUSH([C]) + am_cv_ar_interface=ar + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], + [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + ]) + AC_LANG_POP([C])]) + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + m4_default([$1], + [AC_MSG_ERROR([could not determine $AR interface])]) + ;; +esac +AC_SUBST([AR])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <http://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar <conftest.tar]) + AM_RUN_LOG([cat conftest.dir/file]) + grep GrepMe conftest.dir/file >/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 + +# Autoconf support for the Vala compiler + +# Copyright (C) 2008-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the Vala compiler exists in $PATH. If it is found, the +# variable VALAC is set pointing to its absolute path. Otherwise, it is +# simply set to 'valac'. +# Optionally a minimum release number of the compiler can be requested. +# If the ACTION-IF-FOUND parameter is given, it will be run if a proper +# Vala compiler is found. +# Similarly, if the ACTION-IF-FOUND is given, it will be run if no proper +# Vala compiler is found. It defaults to simply print a warning about the +# situation, but otherwise proceeding with the configuration. +# +# AM_PROG_VALAC([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------------------------- +AC_DEFUN([AM_PROG_VALAC], + [AC_PATH_PROG([VALAC], [valac], [valac]) + AS_IF([test "$VALAC" != valac && test -n "$1"], + [AC_MSG_CHECKING([whether $VALAC is at least version $1]) + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + AS_VERSION_COMPARE([$1], ["$am__vala_version"], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + VALAC=valac])]) + if test "$VALAC" = valac; then + m4_default([$3], + [AC_MSG_WARN([no proper vala compiler found]) + AC_MSG_WARN([you will not be able to compile vala source files])]) + else + m4_default([$2], [:]) + fi]) + +m4_include([m4/gtk-doc.m4]) +m4_include([m4/intltool.m4]) +m4_include([m4/ld-version.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/manywarnings.m4]) +m4_include([m4/spice-compile-warnings.m4]) +m4_include([m4/warnings.m4]) diff --git a/build-aux/ar-lib b/build-aux/ar-lib new file mode 100755 index 0000000..463b9ec --- /dev/null +++ b/build-aux/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010-2014 Free Software Foundation, Inc. +# Written by Peter Rosin <peda@lysator.liu.se>. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <<EOF +Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...] + +Members may be specified in a file named with @FILE. +EOF + exit $? + ;; + -v | --v*) + echo "$me, version $scriptversion" + exit $? + ;; +esac + +if test $# -lt 3; then + func_error "you must specify a program, an action and an archive" +fi + +AR=$1 +shift +while : +do + if test $# -lt 2; then + func_error "you must specify a program, an action and an archive" + fi + case $1 in + -lib | -LIB \ + | -ltcg | -LTCG \ + | -machine* | -MACHINE* \ + | -subsystem* | -SUBSYSTEM* \ + | -verbose | -VERBOSE \ + | -wx* | -WX* ) + AR="$AR $1" + shift + ;; + *) + action=$1 + shift + break + ;; + esac +done +orig_archive=$1 +shift +func_file_conv "$orig_archive" +archive=$file + +# strip leading dash in $action +action=${action#-} + +delete= +extract= +list= +quick= +replace= +index= +create= + +while test -n "$action" +do + case $action in + d*) delete=yes ;; + x*) extract=yes ;; + t*) list=yes ;; + q*) quick=yes ;; + r*) replace=yes ;; + s*) index=yes ;; + S*) ;; # the index is always updated implicitly + c*) create=yes ;; + u*) ;; # TODO: don't ignore the update modifier + v*) ;; # TODO: don't ignore the verbose modifier + *) + func_error "unknown action specified" + ;; + esac + action=${action#?} +done + +case $delete$extract$list$quick$replace,$index in + yes,* | ,yes) + ;; + yesyes*) + func_error "more than one action specified" + ;; + *) + func_error "no action specified" + ;; +esac + +if test -n "$delete"; then + if test ! -f "$orig_archive"; then + func_error "archive not found" + fi + for member + do + case $1 in + @*) + func_at_file "${1#@}" -REMOVE "$archive" + ;; + *) + func_file_conv "$1" + $AR -NOLOGO -REMOVE:"$file" "$archive" || exit $? + ;; + esac + done + +elif test -n "$extract"; then + if test ! -f "$orig_archive"; then + func_error "archive not found" + fi + if test $# -gt 0; then + for member + do + case $1 in + @*) + func_at_file "${1#@}" -EXTRACT "$archive" + ;; + *) + func_file_conv "$1" + $AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $? + ;; + esac + done + else + $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member + do + $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? + done + fi + +elif test -n "$quick$replace"; then + if test ! -f "$orig_archive"; then + if test -z "$create"; then + echo "$me: creating $orig_archive" + fi + orig_archive= + else + orig_archive=$archive + fi + + for member + do + case $1 in + @*) + func_file_conv "${1#@}" + set x "$@" "@$file" + ;; + *) + func_file_conv "$1" + set x "$@" "$file" + ;; + esac + shift + shift + done + + if test -n "$orig_archive"; then + $AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $? + else + $AR -NOLOGO -OUT:"$archive" "$@" || exit $? + fi + +elif test -n "$list"; then + if test ! -f "$orig_archive"; then + func_error "archive not found" + fi + $AR -NOLOGO -LIST "$archive" || exit $? +fi diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..dbfb978 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to <config-patches@gnu.org>. + + +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 <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) 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 -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # 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 ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 0000000..6467c95 --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# 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 <oliva@dcc.unicamp.br>. + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen new file mode 100755 index 0000000..5617eb8 --- /dev/null +++ b/build-aux/git-version-gen @@ -0,0 +1,158 @@ +#!/bin/sh +# Print a version string. +scriptversion=2010-06-14.19; # UTC + +# Copyright (C) 2007-2010 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/. +# It may be run two ways: +# - from a git repository in which the "git describe" command below +# produces useful output (thus requiring at least one signed tag) +# - from a non-git-repo directory containing a .tarball-version file, which +# presumes this script is invoked like "./git-version-gen .tarball-version". + +# In order to use intra-version strings in your project, you will need two +# separate generated version string files: +# +# .tarball-version - present only in a distribution tarball, and not in +# a checked-out repository. Created with contents that were learned at +# the last time autoconf was run, and used by git-version-gen. Must not +# be present in either $(srcdir) or $(builddir) for git-version-gen to +# give accurate answers during normal development with a checked out tree, +# but must be present in a tarball when there is no version control system. +# Therefore, it cannot be used in any dependencies. GNUmakefile has +# hooks to force a reconfigure at distribution time to get the value +# correct, without penalizing normal development with extra reconfigures. +# +# .version - present in a checked-out repository and in a distribution +# tarball. Usable in dependencies, particularly for files that don't +# want to depend on config.h but do want to track version changes. +# Delete this file prior to any autoconf run where you want to rebuild +# files to pick up a version string change; and leave it stale to +# minimize rebuild time after unrelated changes to configure sources. +# +# It is probably wise to add these two files to .gitignore, so that you +# don't accidentally commit either generated file. +# +# Use the following line in your configure.ac, so that $(VERSION) will +# automatically be up-to-date each time configure is run (and note that +# since configure.ac no longer includes a version string, Makefile rules +# should not depend on configure.ac for version updates). +# +# AC_INIT([GNU project], +# m4_esyscmd([build-aux/git-version-gen .tarball-version]), +# [bug-project@example]) +# +# Then use the following lines in your Makefile.am, so that .version +# will be present for dependencies, and so that .tarball-version will +# exist in distribution tarballs. +# +# BUILT_SOURCES = $(top_srcdir)/.version +# $(top_srcdir)/.version: +# echo $(VERSION) > $@-t && mv $@-t $@ +# dist-hook: +# echo $(VERSION) > $(distdir)/.tarball-version + +case $# in + 1|2) ;; + *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version" \ + '[TAG-NORMALIZATION-SED-SCRIPT]' + exit 1;; +esac + +tarball_version_file=$1 +tag_sed_script="${2:-s/x/x/}" +nl=' +' + +# Avoid meddling by environment variable of the same name. +v= + +# First see if there is a tarball-only version file. +# then try "git describe", then default. +if test -f $tarball_version_file +then + v=`cat $tarball_version_file` || exit 1 + case $v in + *$nl*) v= ;; # reject multi-line output + [0-9]*) ;; + *) v= ;; + esac + test -z "$v" \ + && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2 +fi + +if test -n "$v" +then + : # use $v +elif test -d .git \ + && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \ + || git describe --abbrev=4 HEAD 2>/dev/null` \ + && v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \ + && case $v in + v[0-9]*) ;; + *) (exit 1) ;; + esac +then + # Is this a new git that lists number of commits since the last + # tag or the previous older version that did not? + # Newer: v6.10-77-g0f8faeb + # Older: v6.10-g0f8faeb + case $v in + *-*-*) : git describe is okay three part flavor ;; + *-*) + : git describe is older two part flavor + # Recreate the number of commits and rewrite such that the + # result is the same as if we were using the newer version + # of git describe. + vtag=`echo "$v" | sed 's/-.*//'` + numcommits=`git rev-list "$vtag"..HEAD | wc -l` + v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`; + ;; + esac + + # Change the first '-' to a '.', so version-comparing tools work properly. + # Remove the "g" in git describe's output string, to save a byte. + v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`; +else + v=UNKNOWN +fi + +v=`echo "$v" |sed 's/^v//'` + +# Don't declare a version "dirty" merely because a time stamp has changed. +git update-index --refresh > /dev/null 2>&1 + +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty= +case "$dirty" in + '') ;; + *) # Append the suffix only if there isn't one already. + case $v in + *-dirty) ;; + *) v="$v-dirty" ;; + esac ;; +esac + +# Omit the trailing newline, so that m4_esyscmd can use the result directly. +echo "$v" | tr -d "$nl" + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 0000000..0f0a2da --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '<hooked_function_name>_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to <bug-libtool@gnu.org>. +GNU libtool home page: <http://www.gnu.org/software/libtool/>. +General help using GNU software: <http://www.gnu.org/gethelp/>." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <<EOF +# $write_libobj - a libtool object file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object=$write_lobj + +# Name of the non-PIC object +non_pic_object=$write_oldobj + +EOF + $MV "${write_libobj}T" "$write_libobj" + } +} + + +################################################## +# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS # +################################################## + +# func_convert_core_file_wine_to_w32 ARG +# Helper function used by file name conversion functions when $build is *nix, +# and $host is mingw, cygwin, or some other w32 environment. Relies on a +# correctly configured wine environment available, with the winepath program +# in $build's $PATH. +# +# ARG is the $build file name to be converted to w32 format. +# Result is available in $func_convert_core_file_wine_to_w32_result, and will +# be empty on error (or when ARG is empty) +func_convert_core_file_wine_to_w32 () +{ + $debug_cmd + + func_convert_core_file_wine_to_w32_result=$1 + if test -n "$1"; then + # Unfortunately, winepath does not exit with a non-zero error code, so we + # are forced to check the contents of stdout. On the other hand, if the + # command is not found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both error code of + # zero AND non-empty stdout, which explains the odd construction: + func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen <import library>. + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 </dev/null >/dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat <<EOF + +/* $cwrappersource - temporary wrapper executable for $objdir/$outputname + Generated by $PROGRAM (GNU $PACKAGE) $VERSION + + The $output program cannot be directly executed until all the libtool + libraries that it depends on are installed. + + This wrapper executable should never be moved out of the build directory. + If it is, it will not operate correctly. +*/ +EOF + cat <<"EOF" +#ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#include <stdio.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include <direct.h> +# include <process.h> +# include <io.h> +#else +# include <unistd.h> +# include <stdint.h> +# ifdef __CYGWIN__ +# include <io.h> +# endif +#endif +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <<EOF +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) +# define externally_visible volatile +#else +# define externally_visible __attribute__((externally_visible)) volatile +#endif +externally_visible const char * MAGIC_EXE = "$magic_exe"; +const char * LIB_PATH_VARNAME = "$shlibpath_var"; +EOF + + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + func_to_host_path "$temp_rpath" + cat <<EOF +const char * LIB_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * LIB_PATH_VALUE = ""; +EOF + fi + + if test -n "$dllsearchpath"; then + func_to_host_path "$dllsearchpath:" + cat <<EOF +const char * EXE_PATH_VARNAME = "PATH"; +const char * EXE_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * EXE_PATH_VARNAME = ""; +const char * EXE_PATH_VALUE = ""; +EOF + fi + + if test yes = "$fast_install"; then + cat <<EOF +const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ +EOF + else + cat <<EOF +const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ +EOF + fi + + + cat <<"EOF" + +#define LTWRAPPER_OPTION_PREFIX "--lt-" + +static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; +static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; +static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug"; + +int +main (int argc, char *argv[]) +{ + char **newargz; + int newargc; + char *tmp_pathspec; + char *actual_cwrapper_path; + char *actual_cwrapper_name; + char *target_name; + char *lt_argv_zero; + int rval = 127; + + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + newargz = XMALLOC (char *, (size_t) argc + 1); + + /* very simple arg parsing; don't want to rely on getopt + * also, copy all non cwrapper options to newargz, except + * argz[0], which is handled differently + */ + newargc=0; + for (i = 1; i < argc; i++) + { + if (STREQ (argv[i], dumpscript_opt)) + { +EOF + case $host in + *mingw* | *cygwin* ) + # make stdout use "unix" line endings + echo " setmode(1,_O_BINARY);" + ;; + esac + + cat <<"EOF" + lt_dump_script (stdout); + return 0; + } + if (STREQ (argv[i], debug_opt)) + { + lt_debug = 1; + continue; + } + if (STREQ (argv[i], ltwrapper_option_prefix)) + { + /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX + namespace, but it is not one of the ones we know about and + have already dealt with, above (inluding dump-script), then + report an error. Otherwise, targets might begin to believe + they are allowed to use options in the LTWRAPPER_OPTION_PREFIX + namespace. The first time any user complains about this, we'll + need to make LTWRAPPER_OPTION_PREFIX a configure-time option + or a configure.ac-settable value. + */ + lt_fatal (__FILE__, __LINE__, + "unrecognized %s option: '%s'", + ltwrapper_option_prefix, argv[i]); + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); + } + newargz[++newargc] = NULL; + +EOF + cat <<EOF + /* The GNU banner must be the first non-error debug message */ + lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE) $VERSION\n"); +EOF + cat <<"EOF" + lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]); + lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name); + + tmp_pathspec = find_executable (argv[0]); + if (tmp_pathspec == NULL) + lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (before symlink chase) at: %s\n", + tmp_pathspec); + + actual_cwrapper_path = chase_symlinks (tmp_pathspec); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (after symlink chase) at: %s\n", + actual_cwrapper_path); + XFREE (tmp_pathspec); + + actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path)); + strendzap (actual_cwrapper_path, actual_cwrapper_name); + + /* wrapper name transforms */ + strendzap (actual_cwrapper_name, ".exe"); + tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); + XFREE (actual_cwrapper_name); + actual_cwrapper_name = tmp_pathspec; + tmp_pathspec = 0; + + /* target_name transforms -- use actual target program name; might have lt- prefix */ + target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); + strendzap (target_name, ".exe"); + tmp_pathspec = lt_extend_str (target_name, ".exe", 1); + XFREE (target_name); + target_name = tmp_pathspec; + tmp_pathspec = 0; + + lt_debugprintf (__FILE__, __LINE__, + "(main) libtool target name: %s\n", + target_name); +EOF + + cat <<EOF + newargz[0] = + XMALLOC (char, (strlen (actual_cwrapper_path) + + strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); + strcpy (newargz[0], actual_cwrapper_path); + strcat (newargz[0], "$objdir"); + strcat (newargz[0], "/"); +EOF + + cat <<"EOF" + /* stop here, and copy so we don't have to do this twice */ + tmp_pathspec = xstrdup (newargz[0]); + + /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ + strcat (newargz[0], actual_cwrapper_name); + + /* DO want the lt- prefix here if it exists, so use target_name */ + lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); + XFREE (tmp_pathspec); + tmp_pathspec = NULL; +EOF + + case $host_os in + mingw*) + cat <<"EOF" + { + char* p; + while ((p = strchr (newargz[0], '\\')) != NULL) + { + *p = '/'; + } + while ((p = strchr (lt_argv_zero, '\\')) != NULL) + { + *p = '/'; + } + } +EOF + ;; + esac + + cat <<"EOF" + XFREE (target_name); + XFREE (actual_cwrapper_path); + XFREE (actual_cwrapper_name); + + lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ + lt_setenv ("DUALCASE", "1"); /* for MSK sh */ + /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must + be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath) + because on Windows, both *_VARNAMEs are PATH but uninstalled + libraries must come first. */ + lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); + lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); + + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + nonnull (lt_argv_zero)); + for (i = 0; i < newargc; i++) + { + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, nonnull (newargz[i])); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + newargz = prepare_spawn (newargz); + rval = (int) _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + lt_debugprintf (__FILE__, __LINE__, + "(main) failed to launch target \"%s\": %s\n", + lt_argv_zero, nonnull (strerror (errno))); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal (__FILE__, __LINE__, "memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined HAVE_DOS_BASED_FILE_SYSTEM + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then + ldd_output=`ldd conftest` + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i= + ;; + esac + fi + if test -n "$i"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + 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 I believe you do not have" + echo "*** because a test_compile did reveal that the linker did not use it for" + echo "*** its dynamic dependency list that programs get resolved with at runtime." + fi + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + else + # Error occurred in the first compile. Let's try to salvage + # the situation: Compile a separate program for each library. + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $i; then + ldd_output=`ldd conftest` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i= + ;; + esac + fi + if test -n "$i"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + 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 a test_compile did reveal that the linker did not use this one" + echo "*** as a dynamic dependency that programs can get resolved with at runtime." + fi + fi + else + droppeddeps=yes + echo + $ECHO "*** Warning! Library $i is needed by this library but I was not able to" + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method; shift + file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + if test -n "$file_magic_glob"; then + libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` + else + libnameglob=$libname + fi + test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + if test yes = "$want_nocaseglob"; then + shopt -s nocaseglob + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to <bug-automake@gnu.org>." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/test-driver b/build-aux/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/build-aux/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <<END +Usage: + test-driver --test-name=NAME --log-file=PATH --trs-file=PATH + [--expect-failure={yes|no}] [--color-tests={yes|no}] + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] +The '--test-name', '--log-file' and '--trs-file' options are mandatory. +END +} + +test_name= # Used for reporting. +log_file= # Where to save the output of the test script. +trs_file= # Where to save the metadata of the test run. +expect_failure=no +color_tests=no +enable_hard_errors=yes +while test $# -gt 0; do + case $1 in + --help) print_usage; exit $?;; + --version) echo "test-driver $scriptversion"; exit $?;; + --test-name) test_name=$2; shift;; + --log-file) log_file=$2; shift;; + --trs-file) trs_file=$2; shift;; + --color-tests) color_tests=$2; shift;; + --expect-failure) expect_failure=$2; shift;; + --enable-hard-errors) enable_hard_errors=$2; shift;; + --) shift; break;; + -*) usage_error "invalid option: '$1'";; + *) break;; + esac + shift +done + +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + +if test $color_tests = yes; then + # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. + red='' # Red. + grn='' # Green. + lgn='' # Light green. + blu='' # Blue. + mgn='' # Magenta. + std='' # No color. +else + red= grn= lgn= blu= mgn= std= +fi + +do_exit='rm -f $log_file $trs_file; (exit $st); exit $st' +trap "st=129; $do_exit" 1 +trap "st=130; $do_exit" 2 +trap "st=141; $do_exit" 13 +trap "st=143; $do_exit" 15 + +# Test script is run here. +"$@" >$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..3cf80a4 --- /dev/null +++ b/config.h.in @@ -0,0 +1,194 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* always defined to indicate that i18n is enabled */ +#undef ENABLE_NLS + +/* Enable compile-time and run-time bounds-checking, and some warnings. */ + #if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ + # define _FORTIFY_SOURCE 2 + #endif + + +/* GETTEXT package name */ +#undef GETTEXT_PACKAGE + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the `bind_textdomain_codeset' function. */ +#undef HAVE_BIND_TEXTDOMAIN_CODESET + +/* Use the builtin mjpeg decoder? */ +#undef HAVE_BUILTIN_MJPEG + +/* Define to 1 if you have the `clearenv' function. */ +#undef HAVE_CLEARENV + +/* Define to 1 if you have the `dcgettext' function. */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `gdk_event_get_scancode' function. */ +#undef HAVE_GDK_EVENT_GET_SCANCODE + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define if supporting GStreamer 1.0 */ +#undef HAVE_GSTAUDIO + +/* Define if supporting GStreamer 1.0 */ +#undef HAVE_GSTVIDEO + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define if your <locale.h> file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define to 1 if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#undef HAVE_NETINET_IN_H + +/* Define if you have a polkit with polkit_authority_get_sync() */ +#undef HAVE_POLKIT_AUTHORITY_GET_SYNC + +/* Define if you have a polkit with + polkit_authorization_result_get_dismissed() */ +#undef HAVE_POLKIT_AUTHORIZATION_RESULT_GET_DISMISSED + +/* Have PulseAudio support? */ +#undef HAVE_PULSE + +/* Have Quartz? */ +#undef HAVE_QUARTZ + +/* whether Cyrus SASL is available for authentication */ +#undef HAVE_SASL + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtok_r' function. */ +#undef HAVE_STRTOK_R + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <termios.h> header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Have Win32? */ +#undef HAVE_WINDOWS + +/* Define to 1 if you have the <X11/XKBlib.h> header file. */ +#undef HAVE_X11_XKBLIB_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if supporting gdbus */ +#undef USE_GDBUS + +/* Define if supporting gudev */ +#undef USE_GUDEV + +/* Define if libusb has hotplug support */ +#undef USE_LIBUSB_HOTPLUG + +/* Define to build with lz4 support */ +#undef USE_LZ4 + +/* Define if supporting phodav */ +#undef USE_PHODAV + +/* Define if supporting polkit */ +#undef USE_POLKIT + +/* Define if supporting smartcard proxying */ +#undef USE_SMARTCARD + +/* Define if supporting smartcard proxying without libcacard.h */ +#undef USE_SMARTCARD_012 + +/* Define if supporting usbredir proxying */ +#undef USE_USBREDIR + +/* Version number of package */ +#undef VERSION + +/* Whether to use gthread coroutine impl */ +#undef WITH_GTHREAD + +/* Whether to use ucontext coroutine impl */ +#undef WITH_UCONTEXT + +/* Define if compiling with usb.ids support */ +#undef WITH_USBIDS + +/* Whether to use fiber coroutine impl */ +#undef WITH_WINFIBER + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif diff --git a/configure b/configure new file mode 100755 index 0000000..3dbfb02 --- /dev/null +++ b/configure @@ -0,0 +1,23510 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for spice-gtk 0.32. +# +# Report bugs to <spice-devel@lists.freedesktop.org>. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: spice-devel@lists.freedesktop.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + +as_awk_strverscmp=' + # Use only awk features that work with 7th edition Unix awk (1978). + # My, what an old awk you have, Mr. Solaris! + END { + while (length(v1) && length(v2)) { + # Set d1 to be the next thing to compare from v1, and likewise for d2. + # Normally this is a single character, but if v1 and v2 contain digits, + # compare them as integers and fractions as strverscmp does. + if (v1 ~ /^[0-9]/ && v2 ~ /^[0-9]/) { + # Split v1 and v2 into their leading digit string components d1 and d2, + # and advance v1 and v2 past the leading digit strings. + for (len1 = 1; substr(v1, len1 + 1) ~ /^[0-9]/; len1++) continue + for (len2 = 1; substr(v2, len2 + 1) ~ /^[0-9]/; len2++) continue + d1 = substr(v1, 1, len1); v1 = substr(v1, len1 + 1) + d2 = substr(v2, 1, len2); v2 = substr(v2, len2 + 1) + if (d1 ~ /^0/) { + if (d2 ~ /^0/) { + # Compare two fractions. + while (d1 ~ /^0/ && d2 ~ /^0/) { + d1 = substr(d1, 2); len1-- + d2 = substr(d2, 2); len2-- + } + if (len1 != len2 && ! (len1 && len2 && substr(d1, 1, 1) == substr(d2, 1, 1))) { + # The two components differ in length, and the common prefix + # contains only leading zeros. Consider the longer to be less. + d1 = -len1 + d2 = -len2 + } else { + # Otherwise, compare as strings. + d1 = "x" d1 + d2 = "x" d2 + } + } else { + # A fraction is less than an integer. + exit 1 + } + } else { + if (d2 ~ /^0/) { + # An integer is greater than a fraction. + exit 2 + } else { + # Compare two integers. + d1 += 0 + d2 += 0 + } + } + } else { + # The normal case, without worrying about digits. + d1 = substr(v1, 1, 1); v1 = substr(v1, 2) + d2 = substr(v2, 1, 1); v2 = substr(v2, 2) + } + if (d1 < d2) exit 1 + if (d1 > d2) exit 2 + } + # Beware Solaris /usr/xgp4/bin/awk (at least through Solaris 10), + # which mishandles some comparisons of empty strings to integers. + if (length(v2)) exit 1 + if (length(v1)) exit 2 + } +' + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='spice-gtk' +PACKAGE_TARNAME='spice-gtk' +PACKAGE_VERSION='0.32' +PACKAGE_STRING='spice-gtk 0.32' +PACKAGE_BUGREPORT='spice-devel@lists.freedesktop.org' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +enable_option_checking=no +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +BUILD_TESTS_FALSE +BUILD_TESTS_TRUE +SPICE_GTK_REQUIRES +SPICE_GLIB_REQUIRES +SPICE_GTK_CFLAGS +SPICE_GLIB_CFLAGS +SPICE_CFLAGS +WARN_PYFLAGS +WARN_LDFLAGS +WARN_CFLAGS +LZ4_LIBS +LZ4_CFLAGS +VAPIDIR +WITH_VALA_FALSE +WITH_VALA_TRUE +VAPIGEN +VALAC +WITH_CONTROLLER_FALSE +WITH_CONTROLLER_TRUE +G_IR_SCANNER_SYMBOL_PREFIX_FALSE +G_IR_SCANNER_SYMBOL_PREFIX_TRUE +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +WITH_GTHREAD_FALSE +WITH_GTHREAD_TRUE +WITH_WINFIBER_FALSE +WITH_WINFIBER_TRUE +WITH_UCONTEXT_FALSE +WITH_UCONTEXT_TRUE +USB_IDS +ACL_HELPER_DIR +PIE_LDFLAGS +PIE_CFLAGS +POLICYDIR +WITH_POLKIT_FALSE +WITH_POLKIT_TRUE +ACL_LIBS +POLKIT_LIBS +POLKIT_CFLAGS +WITH_USBREDIR_FALSE +WITH_USBREDIR_TRUE +GUDEV_LIBS +GUDEV_CFLAGS +LIBUSB_HOTPLUG_LIBS +LIBUSB_HOTPLUG_CFLAGS +USBREDIR_LIBS +USBREDIR_CFLAGS +WITH_SMARTCARD_FALSE +WITH_SMARTCARD_TRUE +HAVE_SMARTCARD_FALSE +HAVE_SMARTCARD_TRUE +SMARTCARD_LIBS +SMARTCARD_CFLAGS +Z_LIBS +JPEG_LIBS +HAVE_BUILTIN_MJPEG_FALSE +HAVE_BUILTIN_MJPEG_TRUE +HAVE_GSTVIDEO_FALSE +HAVE_GSTVIDEO_TRUE +GSTVIDEO_LIBS +GSTVIDEO_CFLAGS +HAVE_GSTAUDIO_FALSE +HAVE_GSTAUDIO_TRUE +GST_INSPECT_1_0 +GSTAUDIO_LIBS +GSTAUDIO_CFLAGS +HAVE_PULSE_FALSE +HAVE_PULSE_TRUE +PULSE_LIBS +PULSE_CFLAGS +WITH_PHODAV_FALSE +WITH_PHODAV_TRUE +PHODAV_LIBS +PHODAV_CFLAGS +GTHREAD_LIBS +GTHREAD_CFLAGS +CAIRO_LIBS +CAIRO_CFLAGS +GIO_LIBS +GIO_CFLAGS +GOBJECT2_LIBS +GOBJECT2_CFLAGS +GLIB2_LIBS +GLIB2_CFLAGS +PNP_IDS +USE_INTERNAL_PNP_IDS_FALSE +USE_INTERNAL_PNP_IDS_TRUE +WITH_DISPLAY_WINDOWS_FALSE +WITH_DISPLAY_WINDOWS_TRUE +WITH_DISPLAY_QUARTZ_FALSE +WITH_DISPLAY_QUARTZ_TRUE +GTK_LIBS +GTK_CFLAGS +WITH_GTK_FALSE +WITH_GTK_TRUE +GTK_REQUIRED +SASL_LIBS +SASL_CFLAGS +SSL_LIBS +SSL_CFLAGS +PIXMAN_LIBS +PIXMAN_CFLAGS +SPICE_GTK_MICRO_VERSION +SPICE_GTK_MINOR_VERSION +SPICE_GTK_MAJOR_VERSION +COMMON_CFLAGS +SPICE_PROTOCOL_LIBS +SPICE_PROTOCOL_CFLAGS +subdirs +LIBM +OS_WIN32_FALSE +OS_WIN32_TRUE +HAVE_LD_VERSION_SCRIPT_FALSE +HAVE_LD_VERSION_SCRIPT_TRUE +PYTHON +STOW +GTK_DOC_USE_REBASE_FALSE +GTK_DOC_USE_REBASE_TRUE +GTK_DOC_USE_LIBTOOL_FALSE +GTK_DOC_USE_LIBTOOL_TRUE +GTK_DOC_BUILD_PDF_FALSE +GTK_DOC_BUILD_PDF_TRUE +GTK_DOC_BUILD_HTML_FALSE +GTK_DOC_BUILD_HTML_TRUE +ENABLE_GTK_DOC_FALSE +ENABLE_GTK_DOC_TRUE +HAVE_GTK_DOC_FALSE +HAVE_GTK_DOC_TRUE +GTKDOC_DEPS_LIBS +GTKDOC_DEPS_CFLAGS +HTML_DIR +GTKDOC_MKPDF +GTKDOC_REBASE +GTKDOC_CHECK_PATH +GTKDOC_CHECK +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +SPICE_GTK_LOCALEDIR +MKINSTALLDIRS +POSUB +POFILES +PO_IN_DATADIR_FALSE +PO_IN_DATADIR_TRUE +INTLLIBS +INSTOBJEXT +GMOFILES +DATADIRNAME +CATOBJEXT +CATALOGS +MSGFMT_OPTS +GETTEXT_PACKAGE +ALL_LINGUAS +INTLTOOL_PERL +GMSGFMT +MSGFMT +MSGMERGE +XGETTEXT +INTLTOOL_POLICY_RULE +INTLTOOL_SERVICE_RULE +INTLTOOL_THEME_RULE +INTLTOOL_SCHEMAS_RULE +INTLTOOL_CAVES_RULE +INTLTOOL_XML_NOMERGE_RULE +INTLTOOL_XML_RULE +INTLTOOL_KBD_RULE +INTLTOOL_XAM_RULE +INTLTOOL_UI_RULE +INTLTOOL_SOUNDLIST_RULE +INTLTOOL_SHEET_RULE +INTLTOOL_SERVER_RULE +INTLTOOL_PONG_RULE +INTLTOOL_OAF_RULE +INTLTOOL_PROP_RULE +INTLTOOL_KEYS_RULE +INTLTOOL_DIRECTORY_RULE +INTLTOOL_DESKTOP_RULE +intltool__v_merge_options_0 +intltool__v_merge_options_ +INTLTOOL_V_MERGE_OPTIONS +INTLTOOL__v_MERGE_0 +INTLTOOL__v_MERGE_ +INTLTOOL_V_MERGE +INTLTOOL_EXTRACT +INTLTOOL_MERGE +INTLTOOL_UPDATE +USE_NLS +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +OBJDUMP +DLLTOOL +AS +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +ac_ct_AR +AR +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_maintainer_mode +enable_nls +with_html_dir +enable_gtk_doc +enable_gtk_doc_html +enable_gtk_doc_pdf +with_sasl +with_gtk +with_pnp_ids_path +enable_webdav +with_audio +enable_pulse +enable_gstaudio +enable_gstvideo +enable_builtin_mjpeg +enable_smartcard +enable_usbredir +enable_polkit +enable_pie +with_usb_acl_helper_dir +with_usb_ids_path +with_coroutine +enable_introspection +enable_controller +enable_vala +enable_dbus +enable_lz4 +enable_werror +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +GTKDOC_DEPS_CFLAGS +GTKDOC_DEPS_LIBS +SPICE_PROTOCOL_CFLAGS +SPICE_PROTOCOL_LIBS +PIXMAN_CFLAGS +PIXMAN_LIBS +SSL_CFLAGS +SSL_LIBS +SASL_CFLAGS +SASL_LIBS +GTK_CFLAGS +GTK_LIBS +GLIB2_CFLAGS +GLIB2_LIBS +GOBJECT2_CFLAGS +GOBJECT2_LIBS +GIO_CFLAGS +GIO_LIBS +CAIRO_CFLAGS +CAIRO_LIBS +GTHREAD_CFLAGS +GTHREAD_LIBS +PHODAV_CFLAGS +PHODAV_LIBS +PULSE_CFLAGS +PULSE_LIBS +GSTAUDIO_CFLAGS +GSTAUDIO_LIBS +GSTVIDEO_CFLAGS +GSTVIDEO_LIBS +SMARTCARD_CFLAGS +SMARTCARD_LIBS +USBREDIR_CFLAGS +USBREDIR_LIBS +LIBUSB_HOTPLUG_CFLAGS +LIBUSB_HOTPLUG_LIBS +GUDEV_CFLAGS +GUDEV_LIBS +POLKIT_CFLAGS +POLKIT_LIBS +LZ4_CFLAGS +LZ4_LIBS' +ac_subdirs_all='spice-common' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures spice-gtk 0.32 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/spice-gtk] + --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 + case $ac_init_help in + short | recursive ) echo "Configuration of spice-gtk 0.32:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --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-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --disable-nls do not use Native Language Support + --enable-gtk-doc use gtk-doc to build documentation [[default=no]] + --enable-gtk-doc-html build documentation in html format [[default=yes]] + --enable-gtk-doc-pdf build documentation in pdf format [[default=no]] + --enable-webdav=[auto/yes/no] + Enable webdav support [default=auto] + --enable-pulse=[yes/auto/no] + Enable the PulseAudio backend [default=auto] + --enable-gstaudio=[yes/auto/no] + Enable the GStreamer 1.0 audio backend + [default=auto] + --enable-gstvideo=[auto/yes/no] + Enable GStreamer video support [default=auto] + --enable-builtin-mjpeg Enable the builtin mjpeg video decoder [default=yes] + --enable-smartcard=[yes/no/auto] + Enable smartcard support [default=auto] + --enable-usbredir=[auto/yes/no] + Enable usbredir support [default=auto] + --enable-polkit=[auto/yes/no] + Enable PolicyKit support (for the usb acl + helper)[default=auto] + --enable-pie=[auto/yes/no] + Enable position-independent-executable support (for + the usb acl helper)[default=auto] + --enable-introspection=[no/auto/yes] + Enable introspection for this build + --enable-controller Enable controller build [default=yes] + --enable-vala Check for vala requirements [default=no] + --enable-dbus=[auto/yes/no] + Enable dbus support for desktop integration + (disabling automount) [default=auto] + --enable-lz4=[yes/no/auto] + Enable LZ4 compression support [default=auto] + --enable-werror Use -Werror (if supported) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-html-dir=PATH path to installed docs + --with-sasl=[yes/no/auto] + use cyrus SASL for authentication [default=auto] + --with-gtk=[3.0/no] which gtk+ version to compile against [default=3.0] + --with-pnp-ids-path Specify the path to pnp.ids [default=(internal)] + --with-audio=[gstreamer/pulse/auto/no] + For legacy compatibility only + --with-usb-acl-helper-dir=DIR + Directory where the USB ACL helper binary should be + installed + --with-usb-ids-path Specify the path to usb.ids [default=auto] + --with-coroutine=[ucontext/gthread/winfiber/auto] + use ucontext or GThread for coroutines + [default=auto] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + GTKDOC_DEPS_CFLAGS + C compiler flags for GTKDOC_DEPS, overriding pkg-config + GTKDOC_DEPS_LIBS + linker flags for GTKDOC_DEPS, overriding pkg-config + SPICE_PROTOCOL_CFLAGS + C compiler flags for SPICE_PROTOCOL, overriding pkg-config + SPICE_PROTOCOL_LIBS + linker flags for SPICE_PROTOCOL, overriding pkg-config + PIXMAN_CFLAGS + C compiler flags for PIXMAN, overriding pkg-config + PIXMAN_LIBS linker flags for PIXMAN, overriding pkg-config + SSL_CFLAGS C compiler flags for SSL, overriding pkg-config + SSL_LIBS linker flags for SSL, overriding pkg-config + SASL_CFLAGS C compiler flags for SASL, overriding pkg-config + SASL_LIBS linker flags for SASL, overriding pkg-config + GTK_CFLAGS C compiler flags for GTK, overriding pkg-config + GTK_LIBS linker flags for GTK, overriding pkg-config + GLIB2_CFLAGS + C compiler flags for GLIB2, overriding pkg-config + GLIB2_LIBS linker flags for GLIB2, overriding pkg-config + GOBJECT2_CFLAGS + C compiler flags for GOBJECT2, overriding pkg-config + GOBJECT2_LIBS + linker flags for GOBJECT2, overriding pkg-config + GIO_CFLAGS C compiler flags for GIO, overriding pkg-config + GIO_LIBS linker flags for GIO, overriding pkg-config + CAIRO_CFLAGS + C compiler flags for CAIRO, overriding pkg-config + CAIRO_LIBS linker flags for CAIRO, overriding pkg-config + GTHREAD_CFLAGS + C compiler flags for GTHREAD, overriding pkg-config + GTHREAD_LIBS + linker flags for GTHREAD, overriding pkg-config + PHODAV_CFLAGS + C compiler flags for PHODAV, overriding pkg-config + PHODAV_LIBS linker flags for PHODAV, overriding pkg-config + PULSE_CFLAGS + C compiler flags for PULSE, overriding pkg-config + PULSE_LIBS linker flags for PULSE, overriding pkg-config + GSTAUDIO_CFLAGS + C compiler flags for GSTAUDIO, overriding pkg-config + GSTAUDIO_LIBS + linker flags for GSTAUDIO, overriding pkg-config + GSTVIDEO_CFLAGS + C compiler flags for GSTVIDEO, overriding pkg-config + GSTVIDEO_LIBS + linker flags for GSTVIDEO, overriding pkg-config + SMARTCARD_CFLAGS + C compiler flags for SMARTCARD, overriding pkg-config + SMARTCARD_LIBS + linker flags for SMARTCARD, overriding pkg-config + USBREDIR_CFLAGS + C compiler flags for USBREDIR, overriding pkg-config + USBREDIR_LIBS + linker flags for USBREDIR, overriding pkg-config + LIBUSB_HOTPLUG_CFLAGS + C compiler flags for LIBUSB_HOTPLUG, overriding pkg-config + LIBUSB_HOTPLUG_LIBS + linker flags for LIBUSB_HOTPLUG, overriding pkg-config + GUDEV_CFLAGS + C compiler flags for GUDEV, overriding pkg-config + GUDEV_LIBS linker flags for GUDEV, overriding pkg-config + POLKIT_CFLAGS + C compiler flags for POLKIT, overriding pkg-config + POLKIT_LIBS linker flags for POLKIT, overriding pkg-config + LZ4_CFLAGS C compiler flags for LZ4, overriding pkg-config + LZ4_LIBS linker flags for LZ4, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to <spice-devel@lists.freedesktop.org>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +spice-gtk configure 0.32 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------ ## +## Report this to spice-devel@lists.freedesktop.org ## +## ------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +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 spice-gtk $as_me 0.32, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args=$ac_configure_args" '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +# For autoconf < 2.63 + + + + +# SPICE_WARNING(warning) +# SPICE_PRINT_MESSAGES +# ---------------------- +# Collect warnings and print them at the end so they are clearly visible. +# --------------------- + + + + +# SPICE_CHECK_SYSDEPS() +# --------------------- +# Checks for header files and library functions needed by spice-common. +# --------------------- + + + +# SPICE_CHECK_SMARTCARD +# --------------------- +# Adds a --enable-smartcard switch in order to enable/disable smartcard +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the SMARTCARD_CFLAGS and SMARTCARD_LIBS variables, and +# it will define a USE_SMARTCARD preprocessor symbol as well as a HAVE_SMARTCARD +# Makefile conditional. +#---------------------- + + + +# SPICE_CHECK_CELT051 +# ------------------- +# Adds a --disable-celt051 switch in order to enable/disable CELT 0.5.1 +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the CELT051_CFLAGS and CELT051_LIBS variables, and +# it will define a HAVE_CELT051 preprocessor symbol as well as a HAVE_CELT051 +# Makefile conditional. +#-------------------- + + + +# SPICE_CHECK_OPUS +# ---------------- +# Check for the availability of Opus. If found, it will return the flags to use +# in the OPUS_CFLAGS and OPUS_LIBS variables, and it will define a +# HAVE_OPUS preprocessor symbol as well as a HAVE_OPUS Makefile conditional. +# ---------------- + + + +# SPICE_CHECK_PIXMAN +# ------------------ +# Check for the availability of pixman. If found, it will return the flags to +# use in the PIXMAN_CFLAGS and PIXMAN_LIBS variables. +#------------------- + + + +# SPICE_CHECK_GLIB2 +# ----------------- +# Check for the availability of glib2. If found, it will return the flags to +# use in the GLIB2_CFLAGS and GLIB2_LIBS variables. +#------------------ + + +# SPICE_CHECK_PYTHON_MODULES() +# -------------------------- +# Adds a --enable-python-checks configure flags as well as checks for the +# availability of the python modules needed by the python scripts generating +# C code from spice.proto. These checks are not needed when building from +# tarballs so they are disabled by default. +#--------------------------- + + + +# SPICE_CHECK_LZ4 +# --------------- +# Adds a --enable-lz4 switch in order to enable/disable LZ4 compression +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the LZ4_CFLAGS and LZ4_LIBS variables, and +# it will define a USE_LZ4 preprocessor symbol. +# conditional. +# --------------- + + + +# SPICE_CHECK_GSTREAMER(VAR, version, packages-to-check-for, [action-if-found, [action-if-not-found]]) +# --------------------- +# Checks whether the specified GStreamer modules are present and sets the +# corresponding autoconf variables and preprocessor definitions. +# --------------------- + + +# SPICE_CHECK_GSTREAMER_ELEMENTS(gst-inspect, package, elements-to-check-for) +# --------------------- +# Checks that the specified GStreamer elements are installed. If not it +# issues a warning and sets missing_gstreamer_elements. +# --------------------- + + +# SPICE_CHECK_SASL +# ---------------- +# Adds a --with-sasl switch to allow using SASL for authentication. +# Checks whether the required library is available. If it is present, +# it will return the flags to use in SASL_CFLAGS and SASL_LIBS variables, +# and it will define a have_sasl configure variable and a HAVE_SASL preprocessor +# symbol. +# ---------------- + + +# SPICE_CHECK_OPENSSL +# ----------------- +# Check for the availability of openssl. If found, it will return the flags to +# use in the OPENSSL_CFLAGS and OPENSSL_LIBS variables. +#------------------ + + +ac_config_headers="$ac_config_headers config.h" + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='spice-gtk' + VERSION='0.32' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <http://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar lib "link -lib" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar lib "link -lib" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 +$as_echo_n "checking the archiver ($AR) interface... " >&6; } +if ${am_cv_ar_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + am_cv_ar_interface=ar + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int some_variable = 0; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 +$as_echo "$am_cv_ar_interface" >&6; } + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + as_fn_error $? "could not determine $AR interface" "$LINENO" 5 + ;; +esac + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test no != "$with_gnu_ld" && break + ;; + *) + test yes != "$with_gnu_ld" && break + ;; + esac + fi + done + IFS=$lt_save_ifs +else + lt_cv_path_LD=$LD # Let the user override the test with a path. +fi +fi + +LD=$lt_cv_path_LD +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +# 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 + + + + + + + +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + 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}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + enable_dlopen=no + + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + +case "$am__api_version" in + 1.01234) + as_fn_error $? "Automake 1.5 or newer is required to use intltool" "$LINENO" 5 + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo 0.40.0 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n "0.40.0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intltool >= 0.40.0" >&5 +$as_echo_n "checking for intltool >= 0.40.0... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_APPLIED_VERSION found" >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found" >&6; } + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + as_fn_error $? "Your intltool is too old. You need intltool 0.40.0 or later." "$LINENO" 5 +fi + +# Extract the first word of "intltool-update", so it can be a program name with args. +set dummy intltool-update; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_UPDATE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_UPDATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_UPDATE="$INTLTOOL_UPDATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_UPDATE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_UPDATE=$ac_cv_path_INTLTOOL_UPDATE +if test -n "$INTLTOOL_UPDATE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_UPDATE" >&5 +$as_echo "$INTLTOOL_UPDATE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-merge", so it can be a program name with args. +set dummy intltool-merge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_MERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_MERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_MERGE="$INTLTOOL_MERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_MERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_MERGE=$ac_cv_path_INTLTOOL_MERGE +if test -n "$INTLTOOL_MERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_MERGE" >&5 +$as_echo "$INTLTOOL_MERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-extract", so it can be a program name with args. +set dummy intltool-extract; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_EXTRACT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_EXTRACT in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_EXTRACT="$INTLTOOL_EXTRACT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_EXTRACT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_EXTRACT=$ac_cv_path_INTLTOOL_EXTRACT +if test -n "$INTLTOOL_EXTRACT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_EXTRACT" >&5 +$as_echo "$INTLTOOL_EXTRACT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + as_fn_error $? "The intltool scripts were not found. Please install intltool." "$LINENO" 5 +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi + + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " $@;' + + + + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' + + + + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< $@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< $@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.$$RANDOM && mkdir $$_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u $$_it_tmp_dir $< $@ && rmdir $$_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check the gettext tools to make sure they are GNU +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $XGETTEXT in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +XGETTEXT=$ac_cv_path_XGETTEXT +if test -n "$XGETTEXT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGMERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGMERGE=$ac_cv_path_MSGMERGE +if test -n "$MSGMERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGFMT=$ac_cv_path_MSGFMT +if test -n "$MSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_PERL="$INTLTOOL_PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_INTLTOOL_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_PERL=$ac_cv_path_INTLTOOL_PERL +if test -n "$INTLTOOL_PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_PERL" >&5 +$as_echo "$INTLTOOL_PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_PERL"; then + as_fn_error $? "perl not found" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl >= 5.8.1" >&5 +$as_echo_n "checking for perl >= 5.8.1... " >&6; } +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + as_fn_error $? "perl 5.8.1 is required for intltool" "$LINENO" 5 +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IT_PERL_VERSION" >&5 +$as_echo "$IT_PERL_VERSION" >&6; } +fi +if test "x" != "xno-xml"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML::Parser" >&5 +$as_echo_n "checking for XML::Parser... " >&6; } + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + else + as_fn_error $? "XML::Parser perl module is required for intltool" "$LINENO" 5 + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile + + + + + +GETTEXT_PACKAGE=spice-gtk + + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + + for ac_header in locale.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_locale_h = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if ${am_cv_val_LC_MESSAGES+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <locale.h> +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_val_LC_MESSAGES=yes +else + am_cv_val_LC_MESSAGES=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5 +$as_echo "$am_cv_val_LC_MESSAGES" >&6; } + if test $am_cv_val_LC_MESSAGES = yes; then + +$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h + + fi + fi + USE_NLS=yes + + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" +if test "x$ac_cv_header_libintl_h" = xyes; then : + gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in libc" >&5 +$as_echo_n "checking for ngettext in libc... " >&6; } +if ${gt_cv_func_ngettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libintl.h> + +int +main () +{ +return !ngettext ("","", 1) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_ngettext_libc=yes +else + gt_cv_func_ngettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_ngettext_libc" >&5 +$as_echo "$gt_cv_func_ngettext_libc" >&6; } + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in libc" >&5 +$as_echo_n "checking for dgettext in libc... " >&6; } +if ${gt_cv_func_dgettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libintl.h> + +int +main () +{ +return !dgettext ("","") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_dgettext_libc=yes +else + gt_cv_func_dgettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_dgettext_libc" >&5 +$as_echo "$gt_cv_func_dgettext_libc" >&6; } + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + for ac_func in bind_textdomain_codeset +do : + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 +$as_echo_n "checking for bindtextdomain in -lintl... " >&6; } +if ${ac_cv_lib_intl_bindtextdomain+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bindtextdomain (); +int +main () +{ +return bindtextdomain (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_bindtextdomain=yes +else + ac_cv_lib_intl_bindtextdomain=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 +$as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } +if test "x$ac_cv_lib_intl_bindtextdomain" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_ngettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 +$as_echo_n "checking for dgettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_dgettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dgettext (); +int +main () +{ +return dgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_dgettext=yes +else + ac_cv_lib_intl_dgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 +$as_echo "$ac_cv_lib_intl_dgettext" >&6; } +if test "x$ac_cv_lib_intl_dgettext" = xyes; then : + gt_cv_func_dgettext_libintl=yes +fi + +fi + +fi + + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -liconv is needed to use gettext" >&5 +$as_echo_n "checking if -liconv is needed to use gettext... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_ngettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dcgettext in -lintl" >&5 +$as_echo_n "checking for dcgettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_dcgettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dcgettext (); +int +main () +{ +return dcgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_dcgettext=yes +else + ac_cv_lib_intl_dcgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dcgettext" >&5 +$as_echo "$ac_cv_lib_intl_dcgettext" >&6; } +if test "x$ac_cv_lib_intl_dcgettext" = xyes; then : + gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv +else + : +fi + +else + : +fi + + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + for ac_func in bind_textdomain_codeset +do : + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + for ac_func in dcgettext +do : + ac_fn_c_check_func "$LINENO" "dcgettext" "ac_cv_func_dcgettext" +if test "x$ac_cv_func_dcgettext" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DCGETTEXT 1 +_ACEOF + +fi +done + + MSGFMT_OPTS= + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if msgfmt accepts -c" >&5 +$as_echo_n "checking if msgfmt accepts -c... " >&6; } + cat >conftest.foo <<_ACEOF + +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test <foo@bar.xx>\n" +"Language-Team: C <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +_ACEOF +if { { $as_echo "$as_me:${as_lineno-$LINENO}: \$MSGFMT -c -o /dev/null conftest.foo"; } >&5 + ($MSGFMT -c -o /dev/null conftest.foo) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + MSGFMT_OPTS=-c; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +echo "$as_me: failed input was:" >&5 +sed 's/^/| /' conftest.foo >&5 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + case $host in + *-*-solaris*) + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + CATOBJEXT=.mo + DATADIRNAME=lib +fi + + ;; + *-*-openbsd*) + CATOBJEXT=.mo + DATADIRNAME=share + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + +fi + + + + if test "$gt_cv_have_gettext" = "yes" ; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 +$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + ac_config_commands="$ac_config_commands default-1" + + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 +$as_echo_n "checking for catalogs to be installed... " >&6; } + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; 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 + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 +$as_echo "$LINGUAS" >&6; } + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + + + +SPICE_GTK_LOCALEDIR=${datadir}/locale + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + + + gtk_doc_requires="gtk-doc >= 1.14" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtk-doc" >&5 +$as_echo_n "checking for gtk-doc... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_doc_requires\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$gtk_doc_requires") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_gtk_doc=yes +else + have_gtk_doc=no +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gtk_doc" >&5 +$as_echo "$have_gtk_doc" >&6; } + + if test "$have_gtk_doc" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found." >&5 +$as_echo "$as_me: WARNING: + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found." >&2;} + fi + + # Extract the first word of "gtkdoc-check", so it can be a program name with args. +set dummy gtkdoc-check; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_GTKDOC_CHECK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$GTKDOC_CHECK"; then + ac_cv_prog_GTKDOC_CHECK="$GTKDOC_CHECK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_GTKDOC_CHECK="gtkdoc-check.test" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +GTKDOC_CHECK=$ac_cv_prog_GTKDOC_CHECK +if test -n "$GTKDOC_CHECK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5 +$as_echo "$GTKDOC_CHECK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "gtkdoc-check", so it can be a program name with args. +set dummy gtkdoc-check; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_CHECK_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_CHECK_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_CHECK_PATH="$GTKDOC_CHECK_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_CHECK_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_CHECK_PATH=$ac_cv_path_GTKDOC_CHECK_PATH +if test -n "$GTKDOC_CHECK_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK_PATH" >&5 +$as_echo "$GTKDOC_CHECK_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + for ac_prog in gtkdoc-rebase +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_REBASE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_REBASE in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE +if test -n "$GTKDOC_REBASE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5 +$as_echo "$GTKDOC_REBASE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$GTKDOC_REBASE" && break +done +test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true" + + # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args. +set dummy gtkdoc-mkpdf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GTKDOC_MKPDF+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GTKDOC_MKPDF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF +if test -n "$GTKDOC_MKPDF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5 +$as_echo "$GTKDOC_MKPDF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +# Check whether --with-html-dir was given. +if test "${with_html_dir+set}" = set; then : + withval=$with_html_dir; +else + with_html_dir='${datadir}/gtk-doc/html' +fi + + HTML_DIR="$with_html_dir" + + + # Check whether --enable-gtk-doc was given. +if test "${enable_gtk_doc+set}" = set; then : + enableval=$enable_gtk_doc; +else + enable_gtk_doc=no +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5 +$as_echo_n "checking whether to build gtk-doc documentation... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5 +$as_echo "$enable_gtk_doc" >&6; } + + if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then + as_fn_error $? " + You must have $gtk_doc_requires installed to build documentation for + $PACKAGE_NAME. Please install gtk-doc or disable building the + documentation by adding '--disable-gtk-doc' to '$0'." "$LINENO" 5 + fi + + if test "x$PACKAGE_NAME" != "xglib"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 +$as_echo_n "checking for GTKDOC_DEPS... " >&6; } + +if test -n "$GTKDOC_DEPS_CFLAGS"; then + pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTKDOC_DEPS_LIBS"; then + pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + else + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS + GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + fi + + # Check whether --enable-gtk-doc-html was given. +if test "${enable_gtk_doc_html+set}" = set; then : + enableval=$enable_gtk_doc_html; +else + enable_gtk_doc_html=yes +fi + + # Check whether --enable-gtk-doc-pdf was given. +if test "${enable_gtk_doc_pdf+set}" = set; then : + enableval=$enable_gtk_doc_pdf; +else + enable_gtk_doc_pdf=no +fi + + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 + fi + + + if test x$have_gtk_doc = xyes; then + HAVE_GTK_DOC_TRUE= + HAVE_GTK_DOC_FALSE='#' +else + HAVE_GTK_DOC_TRUE='#' + HAVE_GTK_DOC_FALSE= +fi + + if test x$enable_gtk_doc = xyes; then + ENABLE_GTK_DOC_TRUE= + ENABLE_GTK_DOC_FALSE='#' +else + ENABLE_GTK_DOC_TRUE='#' + ENABLE_GTK_DOC_FALSE= +fi + + if test x$enable_gtk_doc_html = xyes; then + GTK_DOC_BUILD_HTML_TRUE= + GTK_DOC_BUILD_HTML_FALSE='#' +else + GTK_DOC_BUILD_HTML_TRUE='#' + GTK_DOC_BUILD_HTML_FALSE= +fi + + if test x$enable_gtk_doc_pdf = xyes; then + GTK_DOC_BUILD_PDF_TRUE= + GTK_DOC_BUILD_PDF_FALSE='#' +else + GTK_DOC_BUILD_PDF_TRUE='#' + GTK_DOC_BUILD_PDF_FALSE= +fi + + if test -n "$LIBTOOL"; then + GTK_DOC_USE_LIBTOOL_TRUE= + GTK_DOC_USE_LIBTOOL_FALSE='#' +else + GTK_DOC_USE_LIBTOOL_TRUE='#' + GTK_DOC_USE_LIBTOOL_FALSE= +fi + + if test -n "$GTKDOC_REBASE"; then + GTK_DOC_USE_REBASE_TRUE= + GTK_DOC_USE_REBASE_FALSE='#' +else + GTK_DOC_USE_REBASE_TRUE='#' + GTK_DOC_USE_REBASE_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + +fi + + +if test "x$ac_cv_prog_cc_c99" = xno; then + as_fn_error $? "C99 compiler is required." "$LINENO" 5 +fi + + +# Extract the first word of "stow", so it can be a program name with args. +set dummy stow; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STOW+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STOW"; then + ac_cv_prog_STOW="$STOW" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STOW="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_STOW" && ac_cv_prog_STOW="no" +fi +fi +STOW=$ac_cv_prog_STOW +if test -n "$STOW"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STOW" >&5 +$as_echo "$STOW" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$STOW" = "xyes" && test -d /usr/local/stow; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: *** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME} ***" >&5 +$as_echo "$as_me: *** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME} ***" >&6;} + ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}" + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + +for ac_prog in python2 python +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PYTHON" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -Wl,--version-script works" >&5 +$as_echo_n "checking if -Wl,--version-script works... " >&6; } +if ${rra_cv_ld_version_script+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + cat > conftest.map <<EOF +VERSION_1 { + global: + sym; + + local: + *; +}; +EOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + rra_cv_ld_version_script=yes +else + rra_cv_ld_version_script=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + rm -f conftest.map + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $rra_cv_ld_version_script" >&5 +$as_echo "$rra_cv_ld_version_script" >&6; } + if test x"$rra_cv_ld_version_script" = xyes; then + HAVE_LD_VERSION_SCRIPT_TRUE= + HAVE_LD_VERSION_SCRIPT_FALSE='#' +else + HAVE_LD_VERSION_SCRIPT_TRUE='#' + HAVE_LD_VERSION_SCRIPT_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native Win32" >&5 +$as_echo_n "checking for native Win32... " >&6; } +case "$host_os" in + *mingw*|*cygwin*) + os_win32=yes + gio_os=gio-windows-2.0 + red_target=Windows + ;; + *) + os_win32=no + gio_os=gio-unix-2.0 + red_target=Unix + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $os_win32" >&5 +$as_echo "$os_win32" >&6; } + if test "$os_win32" = "yes"; then + OS_WIN32_TRUE= + OS_WIN32_FALSE='#' +else + OS_WIN32_TRUE='#' + OS_WIN32_FALSE= +fi + + +for ac_header in sys/socket.h netinet/in.h arpa/inet.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in termios.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default" +if test "x$ac_cv_header_termios_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TERMIOS_H 1 +_ACEOF + +fi + +done + + +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5 +$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; } +if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmw $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _mwvalidcheckl (); +int +main () +{ +return _mwvalidcheckl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mw__mwvalidcheckl=yes +else + ac_cv_lib_mw__mwvalidcheckl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mw__mwvalidcheckl" >&5 +$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; } +if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then : + LIBM=-lmw +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM="$LIBM -lm" +fi + + ;; +*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM=-lm +fi + + ;; +esac + + + + + + +subdirs="$subdirs spice-common" + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SPICE_PROTOCOL" >&5 +$as_echo_n "checking for SPICE_PROTOCOL... " >&6; } + +if test -n "$SPICE_PROTOCOL_CFLAGS"; then + pkg_cv_SPICE_PROTOCOL_CFLAGS="$SPICE_PROTOCOL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"spice-protocol >= 0.12.11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "spice-protocol >= 0.12.11") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SPICE_PROTOCOL_CFLAGS=`$PKG_CONFIG --cflags "spice-protocol >= 0.12.11" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SPICE_PROTOCOL_LIBS"; then + pkg_cv_SPICE_PROTOCOL_LIBS="$SPICE_PROTOCOL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"spice-protocol >= 0.12.11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "spice-protocol >= 0.12.11") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SPICE_PROTOCOL_LIBS=`$PKG_CONFIG --libs "spice-protocol >= 0.12.11" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SPICE_PROTOCOL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "spice-protocol >= 0.12.11" 2>&1` + else + SPICE_PROTOCOL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "spice-protocol >= 0.12.11" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SPICE_PROTOCOL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (spice-protocol >= 0.12.11) were not met: + +$SPICE_PROTOCOL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables SPICE_PROTOCOL_CFLAGS +and SPICE_PROTOCOL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables SPICE_PROTOCOL_CFLAGS +and SPICE_PROTOCOL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + SPICE_PROTOCOL_CFLAGS=$pkg_cv_SPICE_PROTOCOL_CFLAGS + SPICE_PROTOCOL_LIBS=$pkg_cv_SPICE_PROTOCOL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +COMMON_CFLAGS='-I ${top_srcdir}/spice-common/ ${SPICE_PROTOCOL_CFLAGS}' + + +SPICE_GTK_MAJOR_VERSION=`echo $PACKAGE_VERSION | cut -d. -f1` +SPICE_GTK_MINOR_VERSION=`echo $PACKAGE_VERSION | cut -d. -f2` +SPICE_GTK_MICRO_VERSION=`echo $PACKAGE_VERSION | cut -d. -f3 | cut -d- -f1` +if test "x$SPICE_GTK_MICRO_VERSION" = "x"; then : + SPICE_GTK_MICRO_VERSION=0 +fi + + + + + + +srcdir="$(dirname $0)" +if test ! -e "$srcdir/src/vncdisplaykeymap_osx2xtkbd.c"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Text::CSV Perl module" >&5 +$as_echo_n "checking for Text::CSV Perl module... " >&6; } + perl -MText::CSV -e "" >/dev/null 2>&1 + if test $? -ne 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "Text::CSV Perl module is required to compile this package" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } +fi + +SPICE_GLIB_REQUIRES="" +SPICE_GTK_REQUIRES="" + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PIXMAN" >&5 +$as_echo_n "checking for PIXMAN... " >&6; } + +if test -n "$PIXMAN_CFLAGS"; then + pkg_cv_PIXMAN_CFLAGS="$PIXMAN_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pixman-1 >= 0.17.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pixman-1 >= 0.17.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PIXMAN_CFLAGS=`$PKG_CONFIG --cflags "pixman-1 >= 0.17.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PIXMAN_LIBS"; then + pkg_cv_PIXMAN_LIBS="$PIXMAN_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pixman-1 >= 0.17.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pixman-1 >= 0.17.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PIXMAN_LIBS=`$PKG_CONFIG --libs "pixman-1 >= 0.17.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PIXMAN_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pixman-1 >= 0.17.7" 2>&1` + else + PIXMAN_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pixman-1 >= 0.17.7" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PIXMAN_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (pixman-1 >= 0.17.7) were not met: + +$PIXMAN_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables PIXMAN_CFLAGS +and PIXMAN_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables PIXMAN_CFLAGS +and PIXMAN_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + PIXMAN_CFLAGS=$pkg_cv_PIXMAN_CFLAGS + PIXMAN_LIBS=$pkg_cv_PIXMAN_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + +SPICE_GLIB_REQUIRES="${SPICE_GLIB_REQUIRES} pixman-1 >= 0.17.7" + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + +if test -n "$SSL_CFLAGS"; then + pkg_cv_SSL_CFLAGS="$SSL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SSL_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SSL_LIBS"; then + pkg_cv_SSL_LIBS="$SSL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SSL_LIBS=`$PKG_CONFIG --libs "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1` + else + SSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SSL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (openssl) were not met: + +$SSL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables SSL_CFLAGS +and SSL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables SSL_CFLAGS +and SSL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + SSL_CFLAGS=$pkg_cv_SSL_CFLAGS + SSL_LIBS=$pkg_cv_SSL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + +SPICE_GLIB_REQUIRES="${SPICE_GLIB_REQUIRES} openssl" + + + +# Check whether --with-sasl was given. +if test "${with_sasl+set}" = set; then : + withval=$with_sasl; +else + with_sasl="auto" +fi + + + have_sasl=no + if test "x$with_sasl" != "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SASL" >&5 +$as_echo_n "checking for SASL... " >&6; } + +if test -n "$SASL_CFLAGS"; then + pkg_cv_SASL_CFLAGS="$SASL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsasl2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsasl2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SASL_CFLAGS=`$PKG_CONFIG --cflags "libsasl2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SASL_LIBS"; then + pkg_cv_SASL_LIBS="$SASL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsasl2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsasl2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SASL_LIBS=`$PKG_CONFIG --libs "libsasl2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SASL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsasl2" 2>&1` + else + SASL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsasl2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SASL_PKG_ERRORS" >&5 + + have_sasl=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_sasl=no +else + SASL_CFLAGS=$pkg_cv_SASL_CFLAGS + SASL_LIBS=$pkg_cv_SASL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_sasl=yes +fi + if test "x$have_sasl" = "xno" && test "x$with_sasl" = "xyes"; then + as_fn_error $? "Cyrus SASL support requested but libsasl2 could not be found" "$LINENO" 5 + fi + if test "x$have_sasl" = "xyes"; then + +$as_echo "#define HAVE_SASL 1" >>confdefs.h + + fi + fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which gtk+ version to compile against" >&5 +$as_echo_n "checking which gtk+ version to compile against... " >&6; } + +# Check whether --with-gtk was given. +if test "${with_gtk+set}" = set; then : + withval=$with_gtk; case "$with_gtk" in + 3.0) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_gtk" >&5 +$as_echo "$with_gtk" >&6; } ;; + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } ;; + *) as_fn_error $? "invalid gtk version specified" "$LINENO" 5 ;; + esac +else + with_gtk=3.0 +fi + + +case "$with_gtk" in + 3.0) GTK_REQUIRED=3.12 + GTK_ENCODED_VERSION="GDK_VERSION_3_12" + ;; + no) + if test x$enable_gtk_doc = xyes; then : + as_fn_error $? "Without GTK+, gtk-doc must be disabled" "$LINENO" 5 +fi +esac + + + if test "$with_gtk" != "no"; then + WITH_GTK_TRUE= + WITH_GTK_FALSE='#' +else + WITH_GTK_TRUE='#' + WITH_GTK_FALSE= +fi + + +if test "x$with_gtk" != "xno"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5 +$as_echo_n "checking for GTK... " >&6; } + +if test -n "$GTK_CFLAGS"; then + pkg_cv_GTK_CFLAGS="$GTK_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= \$GTK_REQUIRED epoxy\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= $GTK_REQUIRED epoxy") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-3.0 >= $GTK_REQUIRED epoxy" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTK_LIBS"; then + pkg_cv_GTK_LIBS="$GTK_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= \$GTK_REQUIRED epoxy\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= $GTK_REQUIRED epoxy") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-3.0 >= $GTK_REQUIRED epoxy" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-3.0 >= $GTK_REQUIRED epoxy" 2>&1` + else + GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-3.0 >= $GTK_REQUIRED epoxy" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTK_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gtk+-3.0 >= $GTK_REQUIRED epoxy) were not met: + +$GTK_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GTK_CFLAGS +and GTK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GTK_CFLAGS +and GTK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + GTK_CFLAGS=$pkg_cv_GTK_CFLAGS + GTK_LIBS=$pkg_cv_GTK_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + GTK_CFLAGS="$GTK_CFLAGS -DGDK_VERSION_MIN_REQUIRED=$GTK_ENCODED_VERSION \ + -DGDK_VERSION_MAX_ALLOWED=$GTK_ENCODED_VERSION" +fi + + +SPICE_GTK_REQUIRES="${SPICE_GTK_REQUIRES} gtk+-3.0 >= $GTK_REQUIRED" + +# Check for gdk_event_get_scancode function +# This was added in Gdk 3.22 +# The check allows the usage of the function in case the function is +# backported or in case of compilation from Gdk master branch +old_LIBS="$LIBS" +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $GTK_CFLAGS" +LIBS="$LIBS $GTK_LIBS" +for ac_func in gdk_event_get_scancode +do : + ac_fn_c_check_func "$LINENO" "gdk_event_get_scancode" "ac_cv_func_gdk_event_get_scancode" +if test "x$ac_cv_func_gdk_event_get_scancode" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GDK_EVENT_GET_SCANCODE 1 +_ACEOF + +fi +done + +LIBS="$old_LIBS" +CFLAGS="$old_CFLAGS" + +if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-quartz-\$with_gtk\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-quartz-$with_gtk") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_quartz=yes +else + have_quartz=no +fi +if test "x$have_quartz" = "xyes"; then : + +$as_echo "#define HAVE_QUARTZ 1" >>confdefs.h + +fi + if test "x$have_quartz" = "xyes"; then + WITH_DISPLAY_QUARTZ_TRUE= + WITH_DISPLAY_QUARTZ_FALSE='#' +else + WITH_DISPLAY_QUARTZ_TRUE='#' + WITH_DISPLAY_QUARTZ_FALSE= +fi + + +if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-win32-\$with_gtk\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-win32-$with_gtk") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_win32=yes +else + have_win32=no +fi +if test "x$have_win32" = "xyes"; then : + +$as_echo "#define HAVE_WINDOWS 1" >>confdefs.h + +fi + if test "x$have_win32" = "xyes"; then + WITH_DISPLAY_WINDOWS_TRUE= + WITH_DISPLAY_WINDOWS_FALSE='#' +else + WITH_DISPLAY_WINDOWS_TRUE='#' + WITH_DISPLAY_WINDOWS_FALSE= +fi + + +for ac_header in X11/XKBlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "X11/XKBlib.h" "ac_cv_header_X11_XKBlib_h" "$ac_includes_default" +if test "x$ac_cv_header_X11_XKBlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X11_XKBLIB_H 1 +_ACEOF + +fi + +done + + + +# Check whether --with-pnp-ids-path was given. +if test "${with_pnp_ids_path+set}" = set; then : + withval=$with_pnp_ids_path; +else + with_pnp_ids_path="\${pnpdatadir}/pnp.ids" +fi + + + if test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids"; then + USE_INTERNAL_PNP_IDS_TRUE= + USE_INTERNAL_PNP_IDS_FALSE='#' +else + USE_INTERNAL_PNP_IDS_TRUE='#' + USE_INTERNAL_PNP_IDS_FALSE= +fi + +PNP_IDS=$with_pnp_ids_path + +if test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids"; then + EXTERNAL_PNP_IDS="no (internal)" +else + EXTERNAL_PNP_IDS="$with_pnp_ids_path" +fi + +for ac_func in clearenv strtok_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Keep these two definitions in agreement. +GLIB2_REQUIRED="2.36" +GLIB2_ENCODED_VERSION="GLIB_VERSION_2_36" + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB2" >&5 +$as_echo_n "checking for GLIB2... " >&6; } + +if test -n "$GLIB2_CFLAGS"; then + pkg_cv_GLIB2_CFLAGS="$GLIB2_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= \$GLIB2_REQUIRED\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= $GLIB2_REQUIRED") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB2_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= $GLIB2_REQUIRED" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB2_LIBS"; then + pkg_cv_GLIB2_LIBS="$GLIB2_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= \$GLIB2_REQUIRED\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= $GLIB2_REQUIRED") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB2_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= $GLIB2_REQUIRED" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= $GLIB2_REQUIRED" 2>&1` + else + GLIB2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= $GLIB2_REQUIRED" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB2_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (glib-2.0 >= $GLIB2_REQUIRED) were not met: + +$GLIB2_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GLIB2_CFLAGS +and GLIB2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GLIB2_CFLAGS +and GLIB2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + GLIB2_CFLAGS=$pkg_cv_GLIB2_CFLAGS + GLIB2_LIBS=$pkg_cv_GLIB2_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +GLIB2_CFLAGS="$GLIB2_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=$GLIB2_ENCODED_VERSION \ + -DGLIB_VERSION_MAX_ALLOWED=$GLIB2_ENCODED_VERSION" + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GOBJECT2" >&5 +$as_echo_n "checking for GOBJECT2... " >&6; } + +if test -n "$GOBJECT2_CFLAGS"; then + pkg_cv_GOBJECT2_CFLAGS="$GOBJECT2_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GOBJECT2_CFLAGS=`$PKG_CONFIG --cflags "gobject-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GOBJECT2_LIBS"; then + pkg_cv_GOBJECT2_LIBS="$GOBJECT2_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GOBJECT2_LIBS=`$PKG_CONFIG --libs "gobject-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GOBJECT2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gobject-2.0" 2>&1` + else + GOBJECT2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gobject-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GOBJECT2_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gobject-2.0) were not met: + +$GOBJECT2_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GOBJECT2_CFLAGS +and GOBJECT2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GOBJECT2_CFLAGS +and GOBJECT2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + GOBJECT2_CFLAGS=$pkg_cv_GOBJECT2_CFLAGS + GOBJECT2_LIBS=$pkg_cv_GOBJECT2_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GIO" >&5 +$as_echo_n "checking for GIO... " >&6; } + +if test -n "$GIO_CFLAGS"; then + pkg_cv_GIO_CFLAGS="$GIO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.36 \$gio_os\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.36 $gio_os") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GIO_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= 2.36 $gio_os" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GIO_LIBS"; then + pkg_cv_GIO_LIBS="$GIO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.36 \$gio_os\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.36 $gio_os") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GIO_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= 2.36 $gio_os" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-2.0 >= 2.36 $gio_os" 2>&1` + else + GIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-2.0 >= 2.36 $gio_os" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GIO_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gio-2.0 >= 2.36 $gio_os) were not met: + +$GIO_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GIO_CFLAGS +and GIO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GIO_CFLAGS +and GIO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + GIO_CFLAGS=$pkg_cv_GIO_CFLAGS + GIO_LIBS=$pkg_cv_GIO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAIRO" >&5 +$as_echo_n "checking for CAIRO... " >&6; } + +if test -n "$CAIRO_CFLAGS"; then + pkg_cv_CAIRO_CFLAGS="$CAIRO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo >= 1.2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "cairo >= 1.2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CAIRO_CFLAGS=`$PKG_CONFIG --cflags "cairo >= 1.2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CAIRO_LIBS"; then + pkg_cv_CAIRO_LIBS="$CAIRO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo >= 1.2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "cairo >= 1.2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CAIRO_LIBS=`$PKG_CONFIG --libs "cairo >= 1.2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CAIRO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cairo >= 1.2.0" 2>&1` + else + CAIRO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cairo >= 1.2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CAIRO_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (cairo >= 1.2.0) were not met: + +$CAIRO_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables CAIRO_CFLAGS +and CAIRO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables CAIRO_CFLAGS +and CAIRO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + CAIRO_CFLAGS=$pkg_cv_CAIRO_CFLAGS + CAIRO_LIBS=$pkg_cv_CAIRO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTHREAD" >&5 +$as_echo_n "checking for GTHREAD... " >&6; } + +if test -n "$GTHREAD_CFLAGS"; then + pkg_cv_GTHREAD_CFLAGS="$GTHREAD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags "gthread-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTHREAD_LIBS"; then + pkg_cv_GTHREAD_LIBS="$GTHREAD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTHREAD_LIBS=`$PKG_CONFIG --libs "gthread-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTHREAD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gthread-2.0" 2>&1` + else + GTHREAD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gthread-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTHREAD_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gthread-2.0) were not met: + +$GTHREAD_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GTHREAD_CFLAGS +and GTHREAD_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GTHREAD_CFLAGS +and GTHREAD_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see <http://pkg-config.freedesktop.org/>. +See \`config.log' for more details" "$LINENO" 5; } +else + GTHREAD_CFLAGS=$pkg_cv_GTHREAD_CFLAGS + GTHREAD_LIBS=$pkg_cv_GTHREAD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + +# Check whether --enable-webdav was given. +if test "${enable_webdav+set}" = set; then : + enableval=$enable_webdav; +else + enable_webdav="auto" +fi + + +if test "x$enable_webdav" = "xno"; then + have_phodav="no" +else + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PHODAV" >&5 +$as_echo_n "checking for PHODAV... " >&6; } + +if test -n "$PHODAV_CFLAGS"; then + pkg_cv_PHODAV_CFLAGS="$PHODAV_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PHODAV_CFLAGS=`$PKG_CONFIG --cflags "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PHODAV_LIBS"; then + pkg_cv_PHODAV_LIBS="$PHODAV_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PHODAV_LIBS=`$PKG_CONFIG --libs "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PHODAV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91" 2>&1` + else + PHODAV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PHODAV_PKG_ERRORS" >&5 + + have_phodav=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_phodav=no +else + PHODAV_CFLAGS=$pkg_cv_PHODAV_CFLAGS + PHODAV_LIBS=$pkg_cv_PHODAV_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_phodav=yes +fi + + + + if test "x$have_phodav" = "xno" && test "x$enable_webdav" = "xyes"; then + as_fn_error $? "webdav support explicitly requested, but some required packages are not available" "$LINENO" 5 + fi +fi +if test "x$have_phodav" = "xyes"; then : + +$as_echo "#define USE_PHODAV 1" >>confdefs.h + +fi + + if test "x$have_phodav" = "xyes"; then + WITH_PHODAV_TRUE= + WITH_PHODAV_FALSE='#' +else + WITH_PHODAV_TRUE='#' + WITH_PHODAV_FALSE= +fi + + + +# Check whether --with-audio was given. +if test "${with_audio+set}" = set; then : + withval=$with_audio; spice_warnings=$spice_warnings"|--with-audio is deprecated. Use --enable-pulse and/or --enable-gstaudio instead" + case "$with_audio" in + pulse) enable_pulse="yes"; enable_gstaudio="no" ;; + gstreamer) enable_pulse="no"; enable_gstaudio="yes" ;; + no) enable_pulse="no"; enable_gstaudio="no" ;; + esac + +fi + + +# Check whether --enable-pulse was given. +if test "${enable_pulse+set}" = set; then : + enableval=$enable_pulse; +else + enable_pulse="auto" +fi + +if test "x$enable_pulse" != "xno"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PULSE" >&5 +$as_echo_n "checking for PULSE... " >&6; } + +if test -n "$PULSE_CFLAGS"; then + pkg_cv_PULSE_CFLAGS="$PULSE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpulse libpulse-mainloop-glib\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpulse libpulse-mainloop-glib") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PULSE_CFLAGS=`$PKG_CONFIG --cflags "libpulse libpulse-mainloop-glib" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PULSE_LIBS"; then + pkg_cv_PULSE_LIBS="$PULSE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpulse libpulse-mainloop-glib\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpulse libpulse-mainloop-glib") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PULSE_LIBS=`$PKG_CONFIG --libs "libpulse libpulse-mainloop-glib" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PULSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpulse libpulse-mainloop-glib" 2>&1` + else + PULSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpulse libpulse-mainloop-glib" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PULSE_PKG_ERRORS" >&5 + + if test "x$enable_pulse" = "xyes"; then : + as_fn_error $? "PulseAudio requested but not found" "$LINENO" 5 +fi + enable_pulse="no" + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "x$enable_pulse" = "xyes"; then : + as_fn_error $? "PulseAudio requested but not found" "$LINENO" 5 +fi + enable_pulse="no" + +else + PULSE_CFLAGS=$pkg_cv_PULSE_CFLAGS + PULSE_LIBS=$pkg_cv_PULSE_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_PULSE 1" >>confdefs.h + + enable_pulse="yes" +fi + +fi + if test "x$enable_pulse" = "xyes"; then + HAVE_PULSE_TRUE= + HAVE_PULSE_FALSE='#' +else + HAVE_PULSE_TRUE='#' + HAVE_PULSE_FALSE= +fi + + + + +# Check whether --enable-gstaudio was given. +if test "${enable_gstaudio+set}" = set; then : + enableval=$enable_gstaudio; +else + enable_gstaudio="auto" +fi + +if test "x$enable_gstaudio" != "xno"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSTAUDIO" >&5 +$as_echo_n "checking for GSTAUDIO... " >&6; } + +if test -n "$GSTAUDIO_CFLAGS"; then + pkg_cv_GSTAUDIO_CFLAGS="$GSTAUDIO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTAUDIO_CFLAGS=`$PKG_CONFIG --cflags "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GSTAUDIO_LIBS"; then + pkg_cv_GSTAUDIO_LIBS="$GSTAUDIO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTAUDIO_LIBS=`$PKG_CONFIG --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GSTAUDIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" 2>&1` + else + GSTAUDIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GSTAUDIO_PKG_ERRORS" >&5 + + have_gstaudio="no" + if test "x$enable_gstaudio" = "xyes"; then : + as_fn_error $? "GStreamer 1.0 audio requested but not found" "$LINENO" 5 +fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_gstaudio="no" + if test "x$enable_gstaudio" = "xyes"; then : + as_fn_error $? "GStreamer 1.0 audio requested but not found" "$LINENO" 5 +fi + +else + GSTAUDIO_CFLAGS=$pkg_cv_GSTAUDIO_CFLAGS + GSTAUDIO_LIBS=$pkg_cv_GSTAUDIO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_gstaudio="yes" + + + SPICE_REQUIRES=$SPICE_REQUIRES" gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" + +$as_echo "#define HAVE_GSTAUDIO 1" >>confdefs.h + + # Extract the first word of "gst-inspect-1.0", so it can be a program name with args. +set dummy gst-inspect-1.0; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GST_INSPECT_1_0+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GST_INSPECT_1_0 in + [\\/]* | ?:[\\/]*) + ac_cv_path_GST_INSPECT_1_0="$GST_INSPECT_1_0" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GST_INSPECT_1_0="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GST_INSPECT_1_0=$ac_cv_path_GST_INSPECT_1_0 +if test -n "$GST_INSPECT_1_0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GST_INSPECT_1_0" >&5 +$as_echo "$GST_INSPECT_1_0" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$GST_INSPECT_1_0" = x; then : + spice_warnings=$spice_warnings"|Cannot verify that the required runtime GStreamer 1.0 elements are present because gst-inspect-1.0 is missing" +fi + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in audioconvert audioresample appsink + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gst-plugins-base 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in autoaudiosrc + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gst-plugins-good 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + if test x"$missing_gstreamer_elements" = "xyes"; then : + spice_warnings=$spice_warnings"|The GStreamer 1.0 audio backend can be built but may not work." +fi + +fi + + +else + have_gstaudio="no" + +fi + if test "x$have_gstaudio" = "xyes"; then + HAVE_GSTAUDIO_TRUE= + HAVE_GSTAUDIO_FALSE='#' +else + HAVE_GSTAUDIO_TRUE='#' + HAVE_GSTAUDIO_FALSE= +fi + + +if test "x$enable_pulse$have_gstaudio" = "xnono"; then : + spice_warnings=$spice_warnings"|No PulseAudio or GStreamer 1.0 audio decoder, audio will not be streamed" + +fi + +# Check whether --enable-gstvideo was given. +if test "${enable_gstvideo+set}" = set; then : + enableval=$enable_gstvideo; +else + enable_gstvideo="auto" +fi + +if test "x$enable_gstvideo" != "xno"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSTVIDEO" >&5 +$as_echo_n "checking for GSTVIDEO... " >&6; } + +if test -n "$GSTVIDEO_CFLAGS"; then + pkg_cv_GSTVIDEO_CFLAGS="$GSTVIDEO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTVIDEO_CFLAGS=`$PKG_CONFIG --cflags "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GSTVIDEO_LIBS"; then + pkg_cv_GSTVIDEO_LIBS="$GSTVIDEO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTVIDEO_LIBS=`$PKG_CONFIG --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GSTVIDEO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0" 2>&1` + else + GSTVIDEO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GSTVIDEO_PKG_ERRORS" >&5 + + have_gstvideo="no" + if test "x$enable_gstvideo" = "xyes"; then : + as_fn_error $? "GStreamer 1.0 video requested but not found" "$LINENO" 5 +fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_gstvideo="no" + if test "x$enable_gstvideo" = "xyes"; then : + as_fn_error $? "GStreamer 1.0 video requested but not found" "$LINENO" 5 +fi + +else + GSTVIDEO_CFLAGS=$pkg_cv_GSTVIDEO_CFLAGS + GSTVIDEO_LIBS=$pkg_cv_GSTVIDEO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_gstvideo="yes" + + + SPICE_REQUIRES=$SPICE_REQUIRES" gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0" + +$as_echo "#define HAVE_GSTVIDEO 1" >>confdefs.h + + # Extract the first word of "gst-inspect-1.0", so it can be a program name with args. +set dummy gst-inspect-1.0; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GST_INSPECT_1_0+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GST_INSPECT_1_0 in + [\\/]* | ?:[\\/]*) + ac_cv_path_GST_INSPECT_1_0="$GST_INSPECT_1_0" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GST_INSPECT_1_0="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GST_INSPECT_1_0=$ac_cv_path_GST_INSPECT_1_0 +if test -n "$GST_INSPECT_1_0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GST_INSPECT_1_0" >&5 +$as_echo "$GST_INSPECT_1_0" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$GST_INSPECT_1_0" = x; then : + spice_warnings=$spice_warnings"|Cannot verify that the required runtime GStreamer 1.0 elements are present because gst-inspect-1.0 is missing" +fi + missing_gstreamer_elements="" + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in appsrc videoconvert appsink + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gst-plugins-base 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in jpegdec vp8dec + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gst-plugins-good 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in h264parse + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gst-plugins-bad 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + +if test "x$GST_INSPECT_1_0" != x; then : + missing="" + for element in avdec_h264 + do + as_cache_var=`$as_echo "spice_cv_prog_${1}_${element}" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $element GStreamer element" >&5 +$as_echo_n "checking for the $element GStreamer element... " >&6; } +if eval \${$as_cache_var+:} false; then : + $as_echo_n "(cached) " >&6 +else + found=no + "$GST_INSPECT_1_0" $element >/dev/null 2>/dev/null && found=yes + eval "$as_cache_var=$found" +fi +eval ac_res=\$$as_cache_var + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval res=\$$as_cache_var + if test "x$res" = "xno"; then : + missing="$missing $element" +fi + done + if test "x$missing" != x; then : + spice_warnings=$spice_warnings"|The$missing GStreamer element(s) are missing. You should be able to find them in the gstreamer-libav 1.0 package." + missing_gstreamer_elements="yes" +elif test "x$missing_gstreamer_elements" = x; then : + missing_gstreamer_elements="no" +fi + +fi + + if test x"$missing_gstreamer_elements" = "xyes"; then : + spice_warnings=$spice_warnings"|The GStreamer video decoder can be built but may not work." +fi + +fi + + +else + have_gstvideo="no" + +fi + if test "x$have_gstvideo" = "xyes"; then + HAVE_GSTVIDEO_TRUE= + HAVE_GSTVIDEO_FALSE='#' +else + HAVE_GSTVIDEO_TRUE='#' + HAVE_GSTVIDEO_FALSE= +fi + + +# Check whether --enable-builtin-mjpeg was given. +if test "${enable_builtin_mjpeg+set}" = set; then : + enableval=$enable_builtin_mjpeg; +else + enable_builtin_mjpeg="yes" +fi + +if test "x$enable_builtin_mjpeg" = "xyes"; then : + +$as_echo "#define HAVE_BUILTIN_MJPEG 1" >>confdefs.h + +fi + if test "x$enable_builtin_mjpeg" != "xno"; then + HAVE_BUILTIN_MJPEG_TRUE= + HAVE_BUILTIN_MJPEG_FALSE='#' +else + HAVE_BUILTIN_MJPEG_TRUE='#' + HAVE_BUILTIN_MJPEG_FALSE= +fi + + +if test "x$enable_builtin_mjpeg$enable_gstvideo" = "xnono"; then : + spice_warnings=$spice_warnings"|No builtin MJPEG or GStreamer decoder, video will not be streamed" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_destroy_decompress in -ljpeg" >&5 +$as_echo_n "checking for jpeg_destroy_decompress in -ljpeg... " >&6; } +if ${ac_cv_lib_jpeg_jpeg_destroy_decompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char jpeg_destroy_decompress (); +int +main () +{ +return jpeg_destroy_decompress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_jpeg_jpeg_destroy_decompress=yes +else + ac_cv_lib_jpeg_jpeg_destroy_decompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_destroy_decompress" >&5 +$as_echo "$ac_cv_lib_jpeg_jpeg_destroy_decompress" >&6; } +if test "x$ac_cv_lib_jpeg_jpeg_destroy_decompress" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeglib.h" >&5 +$as_echo_n "checking for jpeglib.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +#undef PACKAGE +#undef VERSION +#undef HAVE_STDLIB_H +#include <jpeglib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + JPEG_LIBS='-ljpeg' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jpeg_ok" >&5 +$as_echo "$jpeg_ok" >&6; } +else + as_fn_error $? "jpeglib.h not found" "$LINENO" 5 +fi +rm -f conftest.err conftest.i conftest.$ac_ext +else + as_fn_error $? "libjpeg not found" "$LINENO" 5 +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 +$as_echo_n "checking for deflate in -lz... " >&6; } +if ${ac_cv_lib_z_deflate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char deflate (); +int +main () +{ +return deflate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_deflate=yes +else + ac_cv_lib_z_deflate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 +$as_echo "$ac_cv_lib_z_deflate" >&6; } +if test "x$ac_cv_lib_z_deflate" = xyes; then : + Z_LIBS='-lz' +else + as_fn_error $? "zlib not found" "$LINENO" 5 +fi + + + + + # Check whether --enable-smartcard was given. +if test "${enable_smartcard+set}" = set; then : + enableval=$enable_smartcard; +else + enable_smartcard="auto" +fi + + + have_smartcard=no + if test "x$enable_smartcard" != "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMARTCARD" >&5 +$as_echo_n "checking for SMARTCARD... " >&6; } + +if test -n "$SMARTCARD_CFLAGS"; then + pkg_cv_SMARTCARD_CFLAGS="$SMARTCARD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 2.5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 2.5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_CFLAGS=`$PKG_CONFIG --cflags "libcacard >= 2.5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SMARTCARD_LIBS"; then + pkg_cv_SMARTCARD_LIBS="$SMARTCARD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 2.5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 2.5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_LIBS=`$PKG_CONFIG --libs "libcacard >= 2.5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcacard >= 2.5.1" 2>&1` + else + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcacard >= 2.5.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SMARTCARD_PKG_ERRORS" >&5 + + have_smartcard=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_smartcard=no +else + SMARTCARD_CFLAGS=$pkg_cv_SMARTCARD_CFLAGS + SMARTCARD_LIBS=$pkg_cv_SMARTCARD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_smartcard=yes +fi + if test "x$have_smartcard" = "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMARTCARD" >&5 +$as_echo_n "checking for SMARTCARD... " >&6; } + +if test -n "$SMARTCARD_CFLAGS"; then + pkg_cv_SMARTCARD_CFLAGS="$SMARTCARD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 0.1.2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 0.1.2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_CFLAGS=`$PKG_CONFIG --cflags "libcacard >= 0.1.2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SMARTCARD_LIBS"; then + pkg_cv_SMARTCARD_LIBS="$SMARTCARD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 0.1.2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 0.1.2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_LIBS=`$PKG_CONFIG --libs "libcacard >= 0.1.2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcacard >= 0.1.2" 2>&1` + else + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcacard >= 0.1.2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SMARTCARD_PKG_ERRORS" >&5 + + have_smartcard=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_smartcard=no +else + SMARTCARD_CFLAGS=$pkg_cv_SMARTCARD_CFLAGS + SMARTCARD_LIBS=$pkg_cv_SMARTCARD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_smartcard=yes have_smartcard_012=yes +fi + fi + if test "x$enable_smartcard" != "xauto" && test "x$have_smartcard" = "xno"; then + as_fn_error $? "\"Smartcard support requested but libcacard could not be found\"" "$LINENO" 5 + fi + if test "x$have_smartcard_012" = "xyes"; then + +$as_echo "#define USE_SMARTCARD_012 1" >>confdefs.h + + fi + if test "x$have_smartcard" = "xyes"; then + +$as_echo "#define USE_SMARTCARD 1" >>confdefs.h + + fi + fi + if test "x$have_smartcard" = "xyes"; then + HAVE_SMARTCARD_TRUE= + HAVE_SMARTCARD_FALSE='#' +else + HAVE_SMARTCARD_TRUE='#' + HAVE_SMARTCARD_FALSE= +fi + + + if test "x$have_smartcard" = "xyes"; then + WITH_SMARTCARD_TRUE= + WITH_SMARTCARD_FALSE='#' +else + WITH_SMARTCARD_TRUE='#' + WITH_SMARTCARD_FALSE= +fi + + +# Check whether --enable-usbredir was given. +if test "${enable_usbredir+set}" = set; then : + enableval=$enable_usbredir; +else + enable_usbredir="auto" +fi + + +if test "x$enable_usbredir" = "xno"; then + have_usbredir="no" +else + if ${PKG_CONFIG} libusbredirparser-0.5; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USBREDIR" >&5 +$as_echo_n "checking for USBREDIR... " >&6; } + +if test -n "$USBREDIR_CFLAGS"; then + pkg_cv_USBREDIR_CFLAGS="$USBREDIR_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_USBREDIR_CFLAGS=`$PKG_CONFIG --cflags "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$USBREDIR_LIBS"; then + pkg_cv_USBREDIR_LIBS="$USBREDIR_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_USBREDIR_LIBS=`$PKG_CONFIG --libs "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + USBREDIR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5" 2>&1` + else + USBREDIR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$USBREDIR_PKG_ERRORS" >&5 + + have_usbredir=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_usbredir=no +else + USBREDIR_CFLAGS=$pkg_cv_USBREDIR_CFLAGS + USBREDIR_LIBS=$pkg_cv_USBREDIR_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_usbredir=yes +fi + else + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USBREDIR" >&5 +$as_echo_n "checking for USBREDIR... " >&6; } + +if test -n "$USBREDIR_CFLAGS"; then + pkg_cv_USBREDIR_CFLAGS="$USBREDIR_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_USBREDIR_CFLAGS=`$PKG_CONFIG --cflags "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$USBREDIR_LIBS"; then + pkg_cv_USBREDIR_LIBS="$USBREDIR_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_USBREDIR_LIBS=`$PKG_CONFIG --libs "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + USBREDIR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4" 2>&1` + else + USBREDIR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$USBREDIR_PKG_ERRORS" >&5 + + have_usbredir=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_usbredir=no +else + USBREDIR_CFLAGS=$pkg_cv_USBREDIR_CFLAGS + USBREDIR_LIBS=$pkg_cv_USBREDIR_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_usbredir=yes +fi + fi + if test "x$have_usbredir" = "xno" && test "x$enable_usbredir" = "xyes"; then + as_fn_error $? "usbredir support explicitly requested, but some required packages are not available" "$LINENO" 5 + fi + + # On non windows we need either libusb hotplug support or gudev + if test "x$have_usbredir" = "xyes" && test "x$os_win32" = "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB_HOTPLUG" >&5 +$as_echo_n "checking for LIBUSB_HOTPLUG... " >&6; } + +if test -n "$LIBUSB_HOTPLUG_CFLAGS"; then + pkg_cv_LIBUSB_HOTPLUG_CFLAGS="$LIBUSB_HOTPLUG_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.16\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.16") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBUSB_HOTPLUG_CFLAGS=`$PKG_CONFIG --cflags "libusb-1.0 >= 1.0.16" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBUSB_HOTPLUG_LIBS"; then + pkg_cv_LIBUSB_HOTPLUG_LIBS="$LIBUSB_HOTPLUG_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0 >= 1.0.16\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libusb-1.0 >= 1.0.16") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBUSB_HOTPLUG_LIBS=`$PKG_CONFIG --libs "libusb-1.0 >= 1.0.16" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBUSB_HOTPLUG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb-1.0 >= 1.0.16" 2>&1` + else + LIBUSB_HOTPLUG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb-1.0 >= 1.0.16" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBUSB_HOTPLUG_PKG_ERRORS" >&5 + + have_libusb_hotplug=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_libusb_hotplug=no +else + LIBUSB_HOTPLUG_CFLAGS=$pkg_cv_LIBUSB_HOTPLUG_CFLAGS + LIBUSB_HOTPLUG_LIBS=$pkg_cv_LIBUSB_HOTPLUG_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_libusb_hotplug=yes +fi + if test "x$have_libusb_hotplug" = "xyes"; then + +$as_echo "#define USE_LIBUSB_HOTPLUG 1" >>confdefs.h + + with_usbredir_hotplug="with libusb hotplug" + else + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUDEV" >&5 +$as_echo_n "checking for GUDEV... " >&6; } + +if test -n "$GUDEV_CFLAGS"; then + pkg_cv_GUDEV_CFLAGS="$GUDEV_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gudev-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gudev-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GUDEV_CFLAGS=`$PKG_CONFIG --cflags "gudev-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GUDEV_LIBS"; then + pkg_cv_GUDEV_LIBS="$GUDEV_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gudev-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gudev-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GUDEV_LIBS=`$PKG_CONFIG --libs "gudev-1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GUDEV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gudev-1.0" 2>&1` + else + GUDEV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gudev-1.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GUDEV_PKG_ERRORS" >&5 + + have_gudev=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_gudev=no +else + GUDEV_CFLAGS=$pkg_cv_GUDEV_CFLAGS + GUDEV_LIBS=$pkg_cv_GUDEV_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_gudev=yes +fi + + if test "x$have_gudev" = "xno" && test "x$enable_usbredir" = "xyes"; then + as_fn_error $? "usbredir requested but required gudev is not available" "$LINENO" 5 + fi + if test "x$have_gudev" = "xyes"; then + +$as_echo "#define USE_GUDEV 1" >>confdefs.h + + with_usbredir_hotplug="with gudev hotplug" + else + have_usbredir=no + fi + fi + fi + + if test "x$have_usbredir" = "xyes"; then + +$as_echo "#define USE_USBREDIR 1" >>confdefs.h + + fi +fi + if test "x$have_usbredir" = "xyes"; then + WITH_USBREDIR_TRUE= + WITH_USBREDIR_FALSE='#' +else + WITH_USBREDIR_TRUE='#' + WITH_USBREDIR_FALSE= +fi + + +# Check whether --enable-polkit was given. +if test "${enable_polkit+set}" = set; then : + enableval=$enable_polkit; +else + enable_polkit="auto" +fi + + +if test "x$have_usbredir" = "xyes" && test "x$enable_polkit" != "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for POLKIT" >&5 +$as_echo_n "checking for POLKIT... " >&6; } + +if test -n "$POLKIT_CFLAGS"; then + pkg_cv_POLKIT_CFLAGS="$POLKIT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"polkit-gobject-1 >= 0.96\""; } >&5 + ($PKG_CONFIG --exists --print-errors "polkit-gobject-1 >= 0.96") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_POLKIT_CFLAGS=`$PKG_CONFIG --cflags "polkit-gobject-1 >= 0.96" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$POLKIT_LIBS"; then + pkg_cv_POLKIT_LIBS="$POLKIT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"polkit-gobject-1 >= 0.96\""; } >&5 + ($PKG_CONFIG --exists --print-errors "polkit-gobject-1 >= 0.96") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_POLKIT_LIBS=`$PKG_CONFIG --libs "polkit-gobject-1 >= 0.96" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + POLKIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "polkit-gobject-1 >= 0.96" 2>&1` + else + POLKIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "polkit-gobject-1 >= 0.96" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$POLKIT_PKG_ERRORS" >&5 + + have_polkit=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_polkit=no +else + POLKIT_CFLAGS=$pkg_cv_POLKIT_CFLAGS + POLKIT_LIBS=$pkg_cv_POLKIT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_polkit=yes +fi + ac_fn_c_check_header_mongrel "$LINENO" "acl/libacl.h" "ac_cv_header_acl_libacl_h" "$ac_includes_default" +if test "x$ac_cv_header_acl_libacl_h" = xyes; then : + +else + have_polkit=no +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_file in -lacl" >&5 +$as_echo_n "checking for acl_get_file in -lacl... " >&6; } +if ${ac_cv_lib_acl_acl_get_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get_file (); +int +main () +{ +return acl_get_file (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_acl_acl_get_file=yes +else + ac_cv_lib_acl_acl_get_file=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_get_file" >&5 +$as_echo "$ac_cv_lib_acl_acl_get_file" >&6; } +if test "x$ac_cv_lib_acl_acl_get_file" = xyes; then : + ACL_LIBS=-lacl +else + have_polkit=no +fi + + if test "x$enable_polkit" = "xyes" && test "x$have_polkit" = "xno"; then + as_fn_error $? "PolicyKit support explicitly requested, but some required packages are not available" "$LINENO" 5 + fi + + if test "x$have_polkit" = "xyes"; then + + +$as_echo "#define USE_POLKIT 1" >>confdefs.h + + fi + if test "x$have_polkit" = "xyes"; then + WITH_POLKIT_TRUE= + WITH_POLKIT_FALSE='#' +else + WITH_POLKIT_TRUE='#' + WITH_POLKIT_FALSE= +fi + + POLICYDIR=`${PKG_CONFIG} polkit-gobject-1 --variable=policydir` + + # Check for polkit_authority_get_sync() + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for polkit_authority_get_sync in -lpolkit-gobject-1" >&5 +$as_echo_n "checking for polkit_authority_get_sync in -lpolkit-gobject-1... " >&6; } +if ${ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpolkit-gobject-1 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char polkit_authority_get_sync (); +int +main () +{ +return polkit_authority_get_sync (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync=yes +else + ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync" >&5 +$as_echo "$ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync" >&6; } +if test "x$ac_cv_lib_polkit_gobject_1_polkit_authority_get_sync" = xyes; then : + ac_have_pk_auth_get_sync="1" +else + ac_have_pk_auth_get_sync="0" +fi + + +cat >>confdefs.h <<_ACEOF +#define HAVE_POLKIT_AUTHORITY_GET_SYNC $ac_have_pk_auth_get_sync +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for polkit_authorization_result_get_dismissed in -lpolkit-gobject-1" >&5 +$as_echo_n "checking for polkit_authorization_result_get_dismissed in -lpolkit-gobject-1... " >&6; } +if ${ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpolkit-gobject-1 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char polkit_authorization_result_get_dismissed (); +int +main () +{ +return polkit_authorization_result_get_dismissed (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed=yes +else + ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed" >&5 +$as_echo "$ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed" >&6; } +if test "x$ac_cv_lib_polkit_gobject_1_polkit_authorization_result_get_dismissed" = xyes; then : + ac_have_pk_authorization_result_get_dismissed="1" +else + ac_have_pk_authorization_result_get_dismissed="0" +fi + + +cat >>confdefs.h <<_ACEOF +#define HAVE_POLKIT_AUTHORIZATION_RESULT_GET_DISMISSED $ac_have_pk_authorization_result_get_dismissed +_ACEOF + +else + if false; then + WITH_POLKIT_TRUE= + WITH_POLKIT_FALSE='#' +else + WITH_POLKIT_TRUE='#' + WITH_POLKIT_FALSE= +fi + +fi + +if test "x$have_usbredir" = "xyes" && test "x$have_polkit" != "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building with usbredir support, but *not* building the usb acl helper" >&5 +$as_echo "$as_me: WARNING: Building with usbredir support, but *not* building the usb acl helper" >&2;} +fi + +# Check whether --enable-pie was given. +if test "${enable_pie+set}" = set; then : + enableval=$enable_pie; +else + enable_pie="auto" +fi + + +if test "x$have_polkit" = "xyes" && test "x$enable_pie" != "xno"; then + save_CFLAGS="$CFLAGS" + save_LDFLAGS="$LDFLAGS" + CFLAGS="$CFLAGS -fPIE" + LDFLAGS="$LDFLAGS -pie -Wl,-z,relro -Wl,-z,now" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PIE support" >&5 +$as_echo_n "checking for PIE support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void main () {} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + have_pie=yes +else + have_pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pie" >&5 +$as_echo "$have_pie" >&6; } + if test "x$have_pie" = "xno" && test "x$enable_pie" = "xyes"; then + as_fn_error $? "pie support explicitly requested, but your toolchain does not support it" "$LINENO" 5 + fi + if test "x$have_pie" = "xyes"; then + PIE_CFLAGS="-fPIE" + PIE_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" + + + fi + CFLAGS="$save_CFLAGS" + LDFLAGS="$save_LDFLAGS" +fi + + +# Check whether --with-usb-acl-helper-dir was given. +if test "${with_usb_acl_helper_dir+set}" = set; then : + withval=$with_usb_acl_helper_dir; ACL_HELPER_DIR="$with_usb_acl_helper_dir" +else + ACL_HELPER_DIR="${bindir}/" +fi + + + + +# Check whether --with-usb-ids-path was given. +if test "${with_usb_ids_path+set}" = set; then : + withval=$with_usb_ids_path; USB_IDS="$with_usb_ids_path" +else + USB_IDS="auto" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb.ids" >&5 +$as_echo_n "checking for usb.ids... " >&6; } +if test "x$USB_IDS" = "xauto"; then + if test -n "$PKG_CONFIG"; then + USB_IDS=$($PKG_CONFIG --variable=usbids usbutils) + else + USB_IDS= + fi +fi +if test -n "$USB_IDS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USB_IDS" >&5 +$as_echo "$USB_IDS" >&6; } + + +$as_echo "#define WITH_USBIDS 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } +fi + + +# Check whether --with-coroutine was given. +if test "${with_coroutine+set}" = set; then : + withval=$with_coroutine; +else + with_coroutine=auto +fi + + +case $with_coroutine in + ucontext|gthread|winfiber|auto) ;; + *) as_fn_error $? "Unsupported coroutine type" "$LINENO" 5 +esac + +if test "$with_coroutine" = "auto"; then + if test "$os_win32" = "yes"; then + with_coroutine=winfiber + else + with_coroutine=ucontext + fi +fi + +if test "$with_coroutine" = "ucontext"; then + ac_fn_c_check_func "$LINENO" "makecontext" "ac_cv_func_makecontext" +if test "x$ac_cv_func_makecontext" = xyes; then : + +else + with_coroutine=gthread +fi + + ac_fn_c_check_func "$LINENO" "swapcontext" "ac_cv_func_swapcontext" +if test "x$ac_cv_func_swapcontext" = xyes; then : + +else + with_coroutine=gthread +fi + + ac_fn_c_check_func "$LINENO" "getcontext" "ac_cv_func_getcontext" +if test "x$ac_cv_func_getcontext" = xyes; then : + +else + with_coroutine=gthread +fi + +fi + +WITH_UCONTEXT=0 +WITH_GTHREAD=0 +WITH_WINFIBER=0 + +case $with_coroutine in + ucontext) WITH_UCONTEXT=1 ;; + gthread) WITH_GTHREAD=1 ;; + winfiber) WITH_WINFIBER=1 ;; + *) as_fn_error $? "Unsupported coroutine type" "$LINENO" 5 +esac + + +cat >>confdefs.h <<_ACEOF +#define WITH_UCONTEXT $WITH_UCONTEXT +_ACEOF + + if test "x$WITH_UCONTEXT" = "x1"; then + WITH_UCONTEXT_TRUE= + WITH_UCONTEXT_FALSE='#' +else + WITH_UCONTEXT_TRUE='#' + WITH_UCONTEXT_FALSE= +fi + + + +cat >>confdefs.h <<_ACEOF +#define WITH_WINFIBER $WITH_WINFIBER +_ACEOF + + if test "x$WITH_WINFIBER" = "x1"; then + WITH_WINFIBER_TRUE= + WITH_WINFIBER_FALSE='#' +else + WITH_WINFIBER_TRUE='#' + WITH_WINFIBER_FALSE= +fi + + + +cat >>confdefs.h <<_ACEOF +#define WITH_GTHREAD $WITH_GTHREAD +_ACEOF + + if test "x$WITH_GTHREAD" = "x1"; then + WITH_GTHREAD_TRUE= + WITH_GTHREAD_FALSE='#' +else + WITH_GTHREAD_TRUE='#' + WITH_GTHREAD_FALSE= +fi + + + if test "0" = "1"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"GOBJECT_INTROSPECTION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "GOBJECT_INTROSPECTION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + gobject-introspection-1.0 >= 0.9.4 +else + has_symbol_prefix=yes +fi + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.6.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.6.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= 0.6.7 installed to build spice-gtk" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.6.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.6.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + enable_introspection=$found_introspection + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + + if test "x$has_symbol_prefix" = "xyes"; then + G_IR_SCANNER_SYMBOL_PREFIX_TRUE= + G_IR_SCANNER_SYMBOL_PREFIX_FALSE='#' +else + G_IR_SCANNER_SYMBOL_PREFIX_TRUE='#' + G_IR_SCANNER_SYMBOL_PREFIX_FALSE= +fi + + +# Check whether --enable-controller was given. +if test "${enable_controller+set}" = set; then : + enableval=$enable_controller; +else + enable_controller="yes" +fi + + + if test "x$enable_controller" != "xno"; then + WITH_CONTROLLER_TRUE= + WITH_CONTROLLER_FALSE='#' +else + WITH_CONTROLLER_TRUE='#' + WITH_CONTROLLER_FALSE= +fi + + +# Check whether --enable-vala was given. +if test "${enable_vala+set}" = set; then : + enableval=$enable_vala; +else + enable_vala="no" +fi + + +VALA_REQUIRED=0.14 +if test x$enable_vala = xyes ; then + # check for vala + # Extract the first word of "valac", so it can be a program name with args. +set dummy valac; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VALAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VALAC in + [\\/]* | ?:[\\/]*) + ac_cv_path_VALAC="$VALAC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VALAC="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_VALAC" && ac_cv_path_VALAC="valac" + ;; +esac +fi +VALAC=$ac_cv_path_VALAC +if test -n "$VALAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALAC" >&5 +$as_echo "$VALAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$VALAC" != valac && test -n "$VALA_REQUIRED"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $VALAC is at least version $VALA_REQUIRED" >&5 +$as_echo_n "checking whether $VALAC is at least version $VALA_REQUIRED... " >&6; } + am__vala_version=`$VALAC --version | sed 's/Vala *//'` + as_arg_v1=$VALA_REQUIRED +as_arg_v2="$am__vala_version" +awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null +case $? in #( + 1) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 0) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + 2) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + VALAC=valac ;; #( + *) : + ;; +esac +fi + if test "$VALAC" = valac; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no proper vala compiler found" >&5 +$as_echo "$as_me: WARNING: no proper vala compiler found" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: you will not be able to compile vala source files" >&5 +$as_echo "$as_me: WARNING: you will not be able to compile vala source files" >&2;} + else + : + fi + # Extract the first word of "vapigen", so it can be a program name with args. +set dummy vapigen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_VAPIGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $VAPIGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_VAPIGEN="$VAPIGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VAPIGEN="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_VAPIGEN" && ac_cv_path_VAPIGEN="no" + ;; +esac +fi +VAPIGEN=$ac_cv_path_VAPIGEN +if test -n "$VAPIGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VAPIGEN" >&5 +$as_echo "$VAPIGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$VAPIGEN" == "xno"; then + as_fn_error $? "Cannot find the \"vapigen\" binary in your PATH" "$LINENO" 5 + fi + +fi + + if test "x$enable_vala" = "xyes"; then + WITH_VALA_TRUE= + WITH_VALA_FALSE='#' +else + WITH_VALA_TRUE='#' + WITH_VALA_FALSE= +fi + + +VAPIDIR="${datadir}/vala/vapi" + + +# Check whether --enable-dbus was given. +if test "${enable_dbus+set}" = set; then : + enableval=$enable_dbus; +else + enable_dbus="auto" +fi + + +have_dbus=no +if test "x$enable_dbus" != "xno"; then + +$as_echo "#define USE_GDBUS 1" >>confdefs.h + + have_dbus=yes +else + spice_warnings=$spice_warnings"|No D-Bus support, desktop integration and USB redirection may not work properly" +fi + + + # Check whether --enable-lz4 was given. +if test "${enable_lz4+set}" = set; then : + enableval=$enable_lz4; +else + enable_lz4="auto" +fi + + + if test "x$enable_lz4" != "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4" >&5 +$as_echo_n "checking for LZ4... " >&6; } + +if test -n "$LZ4_CFLAGS"; then + pkg_cv_LZ4_CFLAGS="$LZ4_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LZ4_CFLAGS=`$PKG_CONFIG --cflags "liblz4" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LZ4_LIBS"; then + pkg_cv_LZ4_LIBS="$LZ4_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblz4\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liblz4") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LZ4_LIBS=`$PKG_CONFIG --libs "liblz4" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LZ4_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblz4" 2>&1` + else + LZ4_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblz4" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LZ4_PKG_ERRORS" >&5 + + if test "x$enable_lz4" = "xyes"; then + as_fn_error $? "lz4 support requested but liblz4 could not be found" "$LINENO" 5 + fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "x$enable_lz4" = "xyes"; then + as_fn_error $? "lz4 support requested but liblz4 could not be found" "$LINENO" 5 + fi + +else + LZ4_CFLAGS=$pkg_cv_LZ4_CFLAGS + LZ4_LIBS=$pkg_cv_LZ4_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_lz4=yes + +$as_echo "#define USE_LZ4 1" >>confdefs.h + + +fi + fi + + + +# some glib/gstreamer enums use 1 << 31 +dontwarn="-Wshift-overflow=2" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Werror -Wunknown-warning-option" >&5 +$as_echo_n "checking whether C compiler handles -Werror -Wunknown-warning-option... " >&6; } +if ${gl_cv_warn_c__Werror__Wunknown_warning_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Werror -Wunknown-warning-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Werror__Wunknown_warning_option=yes +else + gl_cv_warn_c__Werror__Wunknown_warning_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Werror__Wunknown_warning_option" >&5 +$as_echo "$gl_cv_warn_c__Werror__Wunknown_warning_option" >&6; } +if test "x$gl_cv_warn_c__Werror__Wunknown_warning_option" = xyes; then : + gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror' +else + gl_unknown_warnings_are_errors= +fi + + + + # Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then : + enableval=$enable_werror; set_werror="$enableval" +else + if test -d $srcdir/.git; then + is_git_version=true + set_werror=yes + else + set_werror=no + fi +fi + + + # List of warnings that are not relevant / wanted + + dontwarn=$dontwarn + + # Don't care about C++ compiler compat + dontwarn="$dontwarn -Wc++-compat" + dontwarn="$dontwarn -Wabi" + dontwarn="$dontwarn -Wdeprecated" + # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional" + # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional-conversion" + # Ignore warnings in /usr/include + dontwarn="$dontwarn -Wsystem-headers" + # Happy for compiler to add struct padding + dontwarn="$dontwarn -Wpadded" + # GCC very confused with -O2 + dontwarn="$dontwarn -Wunreachable-code" + + + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wvla" + dontwarn="$dontwarn -Wundef" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wlong-long" + dontwarn="$dontwarn -Wswitch-default" + dontwarn="$dontwarn -Wswitch-enum" + dontwarn="$dontwarn -Wstrict-overflow" + dontwarn="$dontwarn -Wunsafe-loop-optimizations" + dontwarn="$dontwarn -Wformat-nonliteral" + dontwarn="$dontwarn -Wfloat-equal" + dontwarn="$dontwarn -Wdeclaration-after-statement" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wpacked" + dontwarn="$dontwarn -Wunused-macros" + dontwarn="$dontwarn -Woverlength-strings" + dontwarn="$dontwarn -Wstack-protector" + dontwarn="$dontwarn -Winline" + dontwarn="$dontwarn -Wbad-function-cast" + dontwarn="$dontwarn -Wshadow" + + # Get all possible GCC warnings + + + if test -n "$GCC"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wno-missing-field-initializers is supported" >&5 +$as_echo_n "checking whether -Wno-missing-field-initializers is supported... " >&6; } + if ${gl_cv_cc_nomfi_supported+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror -Wno-missing-field-initializers" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_nomfi_supported=yes +else + gl_cv_cc_nomfi_supported=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_nomfi_supported" >&5 +$as_echo "$gl_cv_cc_nomfi_supported" >&6; } + + if test "$gl_cv_cc_nomfi_supported" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wno-missing-field-initializers is needed" >&5 +$as_echo_n "checking whether -Wno-missing-field-initializers is needed... " >&6; } + if ${gl_cv_cc_nomfi_needed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void f (void) + { + typedef struct { int a; int b; } s_t; + s_t s1 = { 0, }; + } + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_nomfi_needed=no +else + gl_cv_cc_nomfi_needed=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_nomfi_needed" >&5 +$as_echo "$gl_cv_cc_nomfi_needed" >&6; } + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wuninitialized is supported" >&5 +$as_echo_n "checking whether -Wuninitialized is supported... " >&6; } + if ${gl_cv_cc_uninitialized_supported+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror -Wuninitialized" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_uninitialized_supported=yes +else + gl_cv_cc_uninitialized_supported=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_uninitialized_supported" >&5 +$as_echo "$gl_cv_cc_uninitialized_supported" >&6; } + + fi + + # List all gcc warning categories. + # To compare this list to your installed GCC's, run this Bash command: + # + # comm -3 \ + # <(sed -n 's/^ *\(-[^ ]*\) .*/\1/p' manywarnings.m4 | sort) \ + # <(gcc --help=warnings | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort | + # grep -v -x -f <( + # awk '/^[^#]/ {print maybewarn}' ../build-aux/gcc-warning.spec)) + + gl_manywarn_set= + for gl_manywarn_item in \ + -W \ + -Wabi \ + -Waddress \ + -Waggressive-loop-optimizations \ + -Wall \ + -Wattributes \ + -Wbad-function-cast \ + -Wbool-compare \ + -Wbuiltin-macro-redefined \ + -Wcast-align \ + -Wchar-subscripts \ + -Wchkp \ + -Wclobbered \ + -Wcomment \ + -Wcomments \ + -Wcoverage-mismatch \ + -Wcpp \ + -Wdate-time \ + -Wdeprecated \ + -Wdeprecated-declarations \ + -Wdesignated-init \ + -Wdisabled-optimization \ + -Wdiscarded-array-qualifiers \ + -Wdiscarded-qualifiers \ + -Wdiv-by-zero \ + -Wdouble-promotion \ + -Wduplicated-cond \ + -Wempty-body \ + -Wendif-labels \ + -Wenum-compare \ + -Wextra \ + -Wformat-contains-nul \ + -Wformat-extra-args \ + -Wformat-nonliteral \ + -Wformat-security \ + -Wformat-signedness \ + -Wformat-y2k \ + -Wformat-zero-length \ + -Wframe-address \ + -Wfree-nonheap-object \ + -Whsa \ + -Wignored-attributes \ + -Wignored-qualifiers \ + -Wimplicit \ + -Wimplicit-function-declaration \ + -Wimplicit-int \ + -Wincompatible-pointer-types \ + -Winit-self \ + -Winline \ + -Wint-conversion \ + -Wint-to-pointer-cast \ + -Winvalid-memory-model \ + -Winvalid-pch \ + -Wjump-misses-init \ + -Wlogical-not-parentheses \ + -Wlogical-op \ + -Wmain \ + -Wmaybe-uninitialized \ + -Wmemset-transposed-args \ + -Wmisleading-indentation \ + -Wmissing-braces \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-include-dirs \ + -Wmissing-parameter-type \ + -Wmissing-prototypes \ + -Wmultichar \ + -Wnarrowing \ + -Wnested-externs \ + -Wnonnull \ + -Wnonnull-compare \ + -Wnull-dereference \ + -Wodr \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wopenmp-simd \ + -Woverflow \ + -Woverlength-strings \ + -Woverride-init \ + -Wpacked \ + -Wpacked-bitfield-compat \ + -Wparentheses \ + -Wpointer-arith \ + -Wpointer-sign \ + -Wpointer-to-int-cast \ + -Wpragmas \ + -Wreturn-local-addr \ + -Wreturn-type \ + -Wscalar-storage-order \ + -Wsequence-point \ + -Wshadow \ + -Wshift-count-negative \ + -Wshift-count-overflow \ + -Wshift-negative-value \ + -Wsizeof-array-argument \ + -Wsizeof-pointer-memaccess \ + -Wstack-protector \ + -Wstrict-aliasing \ + -Wstrict-overflow \ + -Wstrict-prototypes \ + -Wsuggest-attribute=const \ + -Wsuggest-attribute=format \ + -Wsuggest-attribute=noreturn \ + -Wsuggest-attribute=pure \ + -Wsuggest-final-methods \ + -Wsuggest-final-types \ + -Wswitch \ + -Wswitch-bool \ + -Wswitch-default \ + -Wsync-nand \ + -Wsystem-headers \ + -Wtautological-compare \ + -Wtrampolines \ + -Wtrigraphs \ + -Wtype-limits \ + -Wuninitialized \ + -Wunknown-pragmas \ + -Wunsafe-loop-optimizations \ + -Wunused \ + -Wunused-but-set-parameter \ + -Wunused-but-set-variable \ + -Wunused-function \ + -Wunused-label \ + -Wunused-local-typedefs \ + -Wunused-macros \ + -Wunused-parameter \ + -Wunused-result \ + -Wunused-value \ + -Wunused-variable \ + -Wvarargs \ + -Wvariadic-macros \ + -Wvector-operation-performance \ + -Wvla \ + -Wvolatile-register-var \ + -Wwrite-strings \ + \ + ; do + gl_manywarn_set="$gl_manywarn_set $gl_manywarn_item" + done + + # gcc --help=warnings outputs an unusual form for these options; list + # them here so that the above 'comm' command doesn't report a false match. + gl_manywarn_set="$gl_manywarn_set -Warray-bounds=2" + gl_manywarn_set="$gl_manywarn_set -Wnormalized=nfc" + gl_manywarn_set="$gl_manywarn_set -Wshift-overflow=2" + gl_manywarn_set="$gl_manywarn_set -Wunused-const-variable=2" + + # These are needed for older GCC versions. + if test -n "$GCC"; then + case `($CC --version) 2>/dev/null` in + 'gcc (GCC) '[0-3].* | \ + 'gcc (GCC) '4.[0-7].*) + gl_manywarn_set="$gl_manywarn_set -fdiagnostics-show-option" + gl_manywarn_set="$gl_manywarn_set -funit-at-a-time" + ;; + esac + fi + + # Disable specific options as needed. + if test "$gl_cv_cc_nomfi_needed" = yes; then + gl_manywarn_set="$gl_manywarn_set -Wno-missing-field-initializers" + fi + + if test "$gl_cv_cc_uninitialized_supported" = no; then + gl_manywarn_set="$gl_manywarn_set -Wno-uninitialized" + fi + + maybewarn=$gl_manywarn_set + + + # Remove the ones we don't want, blacklisted earlier + + gl_warn_set= + set x $maybewarn; shift + for gl_warn_item + do + case " $dontwarn " in + *" $gl_warn_item "*) + ;; + *) + gl_warn_set="$gl_warn_set $gl_warn_item" + ;; + esac + done + wantwarn=$gl_warn_set + + + # Check for $CC support of each warning + for w in $wantwarn; do + +as_gl_Warn=`$as_echo "gl_cv_warn_c_$w" | $as_tr_sh` +gl_positive="$w" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles $w" >&5 +$as_echo_n "checking whether C compiler handles $w... " >&6; } +if eval \${$as_gl_Warn+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors $gl_positive" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_gl_Warn=yes" +else + eval "$as_gl_Warn=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +eval ac_res=\$$as_gl_Warn + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_gl_Warn"\" = x"yes"; then : + as_fn_append WARN_CFLAGS " $w" +fi + + + done + + # GNULIB uses '-W' (aka -Wextra) which includes a bunch of stuff. + # Unfortunately, this means you can't simply use '-Wsign-compare' + # with gl_MANYWARN_COMPLEMENT + # So we have -W enabled, and then have to explicitly turn off... + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-sign-compare" >&5 +$as_echo_n "checking whether C compiler handles -Wno-sign-compare... " >&6; } +if ${gl_cv_warn_c__Wno_sign_compare+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wsign-compare" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_sign_compare=yes +else + gl_cv_warn_c__Wno_sign_compare=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_sign_compare" >&5 +$as_echo "$gl_cv_warn_c__Wno_sign_compare" >&6; } +if test "x$gl_cv_warn_c__Wno_sign_compare" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-sign-compare" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-unused-parameter" >&5 +$as_echo_n "checking whether C compiler handles -Wno-unused-parameter... " >&6; } +if ${gl_cv_warn_c__Wno_unused_parameter+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wunused-parameter" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_unused_parameter=yes +else + gl_cv_warn_c__Wno_unused_parameter=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_unused_parameter" >&5 +$as_echo "$gl_cv_warn_c__Wno_unused_parameter" >&6; } +if test "x$gl_cv_warn_c__Wno_unused_parameter" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-unused-parameter" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-missing-field-initializers" >&5 +$as_echo_n "checking whether C compiler handles -Wno-missing-field-initializers... " >&6; } +if ${gl_cv_warn_c__Wno_missing_field_initializers+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wmissing-field-initializers" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_missing_field_initializers=yes +else + gl_cv_warn_c__Wno_missing_field_initializers=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_missing_field_initializers" >&5 +$as_echo "$gl_cv_warn_c__Wno_missing_field_initializers" >&6; } +if test "x$gl_cv_warn_c__Wno_missing_field_initializers" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-missing-field-initializers" +fi + + + # We can't enable this due to horrible spice_usb_device_get_description + # signature + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-format-nonliteral" >&5 +$as_echo_n "checking whether C compiler handles -Wno-format-nonliteral... " >&6; } +if ${gl_cv_warn_c__Wno_format_nonliteral+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wformat-nonliteral" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_format_nonliteral=yes +else + gl_cv_warn_c__Wno_format_nonliteral=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_format_nonliteral" >&5 +$as_echo "$gl_cv_warn_c__Wno_format_nonliteral" >&6; } +if test "x$gl_cv_warn_c__Wno_format_nonliteral" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-format-nonliteral" +fi + + + # We use some deprecated functions to avoid #ifdef hell while maintaining + # compat with older gtk / glib versions + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-deprecated-declarations" >&5 +$as_echo_n "checking whether C compiler handles -Wno-deprecated-declarations... " >&6; } +if ${gl_cv_warn_c__Wno_deprecated_declarations+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wdeprecated-declarations" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_deprecated_declarations=yes +else + gl_cv_warn_c__Wno_deprecated_declarations=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_deprecated_declarations" >&5 +$as_echo "$gl_cv_warn_c__Wno_deprecated_declarations" >&6; } +if test "x$gl_cv_warn_c__Wno_deprecated_declarations" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-deprecated-declarations" +fi + + + + + + # GNULIB expects this to be part of -Wc++-compat, but we turn + # that one off, so we need to manually enable this again + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wjump-misses-init" >&5 +$as_echo_n "checking whether C compiler handles -Wjump-misses-init... " >&6; } +if ${gl_cv_warn_c__Wjump_misses_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wjump-misses-init" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wjump_misses_init=yes +else + gl_cv_warn_c__Wjump_misses_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wjump_misses_init" >&5 +$as_echo "$gl_cv_warn_c__Wjump_misses_init" >&6; } +if test "x$gl_cv_warn_c__Wjump_misses_init" = xyes; then : + as_fn_append WARN_CFLAGS " -Wjump-misses-init" +fi + + + + # GNULIB turns on -Wformat=2 which implies -Wformat-nonliteral, + # so we need to manually re-exclude it. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-format-nonliteral" >&5 +$as_echo_n "checking whether C compiler handles -Wno-format-nonliteral... " >&6; } +if ${gl_cv_warn_c__Wno_format_nonliteral+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wformat-nonliteral" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_format_nonliteral=yes +else + gl_cv_warn_c__Wno_format_nonliteral=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_format_nonliteral" >&5 +$as_echo "$gl_cv_warn_c__Wno_format_nonliteral" >&6; } +if test "x$gl_cv_warn_c__Wno_format_nonliteral" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-format-nonliteral" +fi + + + + # This should be < 1024 really. pixman_utils is the blackspot + # preventing lower usage + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wframe-larger-than=9216" >&5 +$as_echo_n "checking whether C compiler handles -Wframe-larger-than=9216... " >&6; } +if ${gl_cv_warn_c__Wframe_larger_than_9216+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wframe-larger-than=9216" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wframe_larger_than_9216=yes +else + gl_cv_warn_c__Wframe_larger_than_9216=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wframe_larger_than_9216" >&5 +$as_echo "$gl_cv_warn_c__Wframe_larger_than_9216" >&6; } +if test "x$gl_cv_warn_c__Wframe_larger_than_9216" = xyes; then : + as_fn_append WARN_CFLAGS " -Wframe-larger-than=9216" +fi + + + + # Use improved glibc headers + + + # Extra special flags + case $host in + *-*-linux*) + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fstack-protector-all" >&5 +$as_echo_n "checking whether C compiler handles -fstack-protector-all... " >&6; } +if ${gl_cv_warn_c__fstack_protector_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fstack-protector-all" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fstack_protector_all=yes +else + gl_cv_warn_c__fstack_protector_all=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fstack_protector_all" >&5 +$as_echo "$gl_cv_warn_c__fstack_protector_all" >&6; } +if test "x$gl_cv_warn_c__fstack_protector_all" = xyes; then : + as_fn_append WARN_CFLAGS " -fstack-protector-all" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles --param=ssp-buffer-size=4" >&5 +$as_echo_n "checking whether C compiler handles --param=ssp-buffer-size=4... " >&6; } +if ${gl_cv_warn_c___param_ssp_buffer_size_4+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors --param=ssp-buffer-size=4" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c___param_ssp_buffer_size_4=yes +else + gl_cv_warn_c___param_ssp_buffer_size_4=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c___param_ssp_buffer_size_4" >&5 +$as_echo "$gl_cv_warn_c___param_ssp_buffer_size_4" >&6; } +if test "x$gl_cv_warn_c___param_ssp_buffer_size_4" = xyes; then : + as_fn_append WARN_CFLAGS " --param=ssp-buffer-size=4" +fi + + + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fexceptions" >&5 +$as_echo_n "checking whether C compiler handles -fexceptions... " >&6; } +if ${gl_cv_warn_c__fexceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fexceptions" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fexceptions=yes +else + gl_cv_warn_c__fexceptions=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fexceptions" >&5 +$as_echo "$gl_cv_warn_c__fexceptions" >&6; } +if test "x$gl_cv_warn_c__fexceptions" = xyes; then : + as_fn_append WARN_CFLAGS " -fexceptions" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fasynchronous-unwind-tables" >&5 +$as_echo_n "checking whether C compiler handles -fasynchronous-unwind-tables... " >&6; } +if ${gl_cv_warn_c__fasynchronous_unwind_tables+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fasynchronous-unwind-tables" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fasynchronous_unwind_tables=yes +else + gl_cv_warn_c__fasynchronous_unwind_tables=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fasynchronous_unwind_tables" >&5 +$as_echo "$gl_cv_warn_c__fasynchronous_unwind_tables" >&6; } +if test "x$gl_cv_warn_c__fasynchronous_unwind_tables" = xyes; then : + as_fn_append WARN_CFLAGS " -fasynchronous-unwind-tables" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fdiagnostics-show-option" >&5 +$as_echo_n "checking whether C compiler handles -fdiagnostics-show-option... " >&6; } +if ${gl_cv_warn_c__fdiagnostics_show_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fdiagnostics-show-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fdiagnostics_show_option=yes +else + gl_cv_warn_c__fdiagnostics_show_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fdiagnostics_show_option" >&5 +$as_echo "$gl_cv_warn_c__fdiagnostics_show_option" >&6; } +if test "x$gl_cv_warn_c__fdiagnostics_show_option" = xyes; then : + as_fn_append WARN_CFLAGS " -fdiagnostics-show-option" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -funit-at-a-time" >&5 +$as_echo_n "checking whether C compiler handles -funit-at-a-time... " >&6; } +if ${gl_cv_warn_c__funit_at_a_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -funit-at-a-time" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__funit_at_a_time=yes +else + gl_cv_warn_c__funit_at_a_time=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__funit_at_a_time" >&5 +$as_echo "$gl_cv_warn_c__funit_at_a_time" >&6; } +if test "x$gl_cv_warn_c__funit_at_a_time" = xyes; then : + as_fn_append WARN_CFLAGS " -funit-at-a-time" +fi + + + + # Need -fipa-pure-const in order to make -Wsuggest-attribute=pure + # fire even without -O. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -fipa-pure-const" >&5 +$as_echo_n "checking whether C compiler handles -fipa-pure-const... " >&6; } +if ${gl_cv_warn_c__fipa_pure_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -fipa-pure-const" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__fipa_pure_const=yes +else + gl_cv_warn_c__fipa_pure_const=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__fipa_pure_const" >&5 +$as_echo "$gl_cv_warn_c__fipa_pure_const" >&6; } +if test "x$gl_cv_warn_c__fipa_pure_const" = xyes; then : + as_fn_append WARN_CFLAGS " -fipa-pure-const" +fi + + + + # We should eventually enable this, but right now there are at + # least 75 functions triggering warnings. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-suggest-attribute=pure" >&5 +$as_echo_n "checking whether C compiler handles -Wno-suggest-attribute=pure... " >&6; } +if ${gl_cv_warn_c__Wno_suggest_attribute_pure+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wsuggest-attribute=pure" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_suggest_attribute_pure=yes +else + gl_cv_warn_c__Wno_suggest_attribute_pure=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_suggest_attribute_pure" >&5 +$as_echo "$gl_cv_warn_c__Wno_suggest_attribute_pure" >&6; } +if test "x$gl_cv_warn_c__Wno_suggest_attribute_pure" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-suggest-attribute=pure" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-suggest-attribute=const" >&5 +$as_echo_n "checking whether C compiler handles -Wno-suggest-attribute=const... " >&6; } +if ${gl_cv_warn_c__Wno_suggest_attribute_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wsuggest-attribute=const" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_suggest_attribute_const=yes +else + gl_cv_warn_c__Wno_suggest_attribute_const=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_suggest_attribute_const" >&5 +$as_echo "$gl_cv_warn_c__Wno_suggest_attribute_const" >&6; } +if test "x$gl_cv_warn_c__Wno_suggest_attribute_const" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-suggest-attribute=const" +fi + + + + if test "$set_werror" = "yes" + then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Werror" >&5 +$as_echo_n "checking whether C compiler handles -Werror... " >&6; } +if ${gl_cv_warn_c__Werror+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Werror=yes +else + gl_cv_warn_c__Werror=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Werror" >&5 +$as_echo "$gl_cv_warn_c__Werror" >&6; } +if test "x$gl_cv_warn_c__Werror" = xyes; then : + as_fn_append WARN_CFLAGS " -Werror" +fi + + + fi + + WARN_LDFLAGS=$WARN_CFLAGS + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler handles -Wno-write-strings" >&5 +$as_echo_n "checking whether C compiler handles -Wno-write-strings... " >&6; } +if ${gl_cv_warn_c__Wno_write_strings+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CFLAGS" + as_fn_append CFLAGS " $gl_unknown_warnings_are_errors -Wwrite-strings" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_warn_c__Wno_write_strings=yes +else + gl_cv_warn_c__Wno_write_strings=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_c__Wno_write_strings" >&5 +$as_echo "$gl_cv_warn_c__Wno_write_strings" >&6; } +if test "x$gl_cv_warn_c__Wno_write_strings" = xyes; then : + as_fn_append WARN_CFLAGS " -Wno-write-strings" +fi + + + WARN_PYFLAGS=$WARN_CFLAGS + + + +SPICE_CFLAGS="$SPICE_CFLAGS $WARN_CFLAGS" + + + +SPICE_GLIB_CFLAGS="$PIXMAN_CFLAGS $PULSE_CFLAGS $GSTAUDIO_CFLAGS $GSTVIDEO_CFLAGS $GLIB2_CFLAGS $GIO_CFLAGS $GOBJECT2_CFLAGS $SSL_CFLAGS $SASL_CFLAGS" +SPICE_GTK_CFLAGS="$SPICE_GLIB_CFLAGS $GTK_CFLAGS " + + + + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + + if test x"$enable_static" = xyes; then + BUILD_TESTS_TRUE= + BUILD_TESTS_FALSE='#' +else + BUILD_TESTS_TRUE='#' + BUILD_TESTS_FALSE= +fi + + +ac_config_files="$ac_config_files Makefile spice-client-glib-2.0.pc spice-client-gtk-3.0.pc spice-controller.pc data/Makefile po/Makefile.in src/Makefile src/spice-version.h src/controller/Makefile doc/Makefile doc/reference/Makefile man/Makefile vapi/Makefile tests/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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + 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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + + ac_config_commands="$ac_config_commands po/stamp-it" + + +if test -z "${HAVE_GTK_DOC_TRUE}" && test -z "${HAVE_GTK_DOC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GTK_DOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GTK_DOC_USE_REBASE_TRUE}" && test -z "${GTK_DOC_USE_REBASE_FALSE}"; then + as_fn_error $? "conditional \"GTK_DOC_USE_REBASE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OS_WIN32_TRUE}" && test -z "${OS_WIN32_FALSE}"; then + as_fn_error $? "conditional \"OS_WIN32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_GTK_TRUE}" && test -z "${WITH_GTK_FALSE}"; then + as_fn_error $? "conditional \"WITH_GTK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_DISPLAY_QUARTZ_TRUE}" && test -z "${WITH_DISPLAY_QUARTZ_FALSE}"; then + as_fn_error $? "conditional \"WITH_DISPLAY_QUARTZ\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_DISPLAY_WINDOWS_TRUE}" && test -z "${WITH_DISPLAY_WINDOWS_FALSE}"; then + as_fn_error $? "conditional \"WITH_DISPLAY_WINDOWS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_INTERNAL_PNP_IDS_TRUE}" && test -z "${USE_INTERNAL_PNP_IDS_FALSE}"; then + as_fn_error $? "conditional \"USE_INTERNAL_PNP_IDS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_PHODAV_TRUE}" && test -z "${WITH_PHODAV_FALSE}"; then + as_fn_error $? "conditional \"WITH_PHODAV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PULSE_TRUE}" && test -z "${HAVE_PULSE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PULSE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GSTAUDIO_TRUE}" && test -z "${HAVE_GSTAUDIO_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GSTAUDIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GSTVIDEO_TRUE}" && test -z "${HAVE_GSTVIDEO_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GSTVIDEO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_BUILTIN_MJPEG_TRUE}" && test -z "${HAVE_BUILTIN_MJPEG_FALSE}"; then + as_fn_error $? "conditional \"HAVE_BUILTIN_MJPEG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SMARTCARD_TRUE}" && test -z "${HAVE_SMARTCARD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SMARTCARD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_SMARTCARD_TRUE}" && test -z "${WITH_SMARTCARD_FALSE}"; then + as_fn_error $? "conditional \"WITH_SMARTCARD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_USBREDIR_TRUE}" && test -z "${WITH_USBREDIR_FALSE}"; then + as_fn_error $? "conditional \"WITH_USBREDIR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_POLKIT_TRUE}" && test -z "${WITH_POLKIT_FALSE}"; then + as_fn_error $? "conditional \"WITH_POLKIT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_POLKIT_TRUE}" && test -z "${WITH_POLKIT_FALSE}"; then + as_fn_error $? "conditional \"WITH_POLKIT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_UCONTEXT_TRUE}" && test -z "${WITH_UCONTEXT_FALSE}"; then + as_fn_error $? "conditional \"WITH_UCONTEXT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_WINFIBER_TRUE}" && test -z "${WITH_WINFIBER_FALSE}"; then + as_fn_error $? "conditional \"WITH_WINFIBER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_GTHREAD_TRUE}" && test -z "${WITH_GTHREAD_FALSE}"; then + as_fn_error $? "conditional \"WITH_GTHREAD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${G_IR_SCANNER_SYMBOL_PREFIX_TRUE}" && test -z "${G_IR_SCANNER_SYMBOL_PREFIX_FALSE}"; then + as_fn_error $? "conditional \"G_IR_SCANNER_SYMBOL_PREFIX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_CONTROLLER_TRUE}" && test -z "${WITH_CONTROLLER_FALSE}"; then + as_fn_error $? "conditional \"WITH_CONTROLLER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_VALA_TRUE}" && test -z "${WITH_VALA_FALSE}"; then + as_fn_error $? "conditional \"WITH_VALA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TESTS_TRUE}" && test -z "${BUILD_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by spice-gtk $as_me 0.32, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to <spice-devel@lists.freedesktop.org>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +spice-gtk config.status 0.32 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + CONFIG_FILES=$CONFIG_FILES" '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + CONFIG_HEADERS=$CONFIG_HEADERS" '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) 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 || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in AS \ +DLLTOOL \ +OBJDUMP \ +SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "spice-client-glib-2.0.pc") CONFIG_FILES="$CONFIG_FILES spice-client-glib-2.0.pc" ;; + "spice-client-gtk-3.0.pc") CONFIG_FILES="$CONFIG_FILES spice-client-gtk-3.0.pc" ;; + "spice-controller.pc") CONFIG_FILES="$CONFIG_FILES spice-controller.pc" ;; + "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/spice-version.h") CONFIG_FILES="$CONFIG_FILES src/spice-version.h" ;; + "src/controller/Makefile") CONFIG_FILES="$CONFIG_FILES src/controller/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/reference/Makefile") CONFIG_FILES="$CONFIG_FILES doc/reference/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "vapi/Makefile") CONFIG_FILES="$CONFIG_FILES vapi/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + 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 '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "default-1":C) case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac ;; + "po/stamp-it":C) + if ! grep "^# INTLTOOL_MAKEFILE$" "po/Makefile.in" > /dev/null ; then + as_fn_error $? "po/Makefile.in.in was not created by intltoolize." "$LINENO" 5 + fi + rm -f "po/stamp-it" "po/stamp-it.tmp" "po/POTFILES" "po/Makefile.tmp" + >"po/stamp-it.tmp" + sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/po/POTFILES.in" | sed '$!s/$/ \\/' >"po/POTFILES" + + sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r po/POTFILES + } + ' "po/Makefile.in" >"po/Makefile" + rm -f "po/Makefile.tmp" + mv "po/stamp-it.tmp" "po/stamp-it" + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -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=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args=$ac_sub_configure_args" '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 + fi + + cd "$ac_popdir" + done +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: + + Spice-Gtk $VERSION + ============== + + prefix: ${prefix} + c compiler: ${CC} + Target: ${red_target} + + Gtk: ${with_gtk} + Coroutine: ${with_coroutine} + PulseAudio: ${enable_pulse} + GStreamer Audio: ${have_gstaudio} + GStreamer Video: ${have_gstvideo} + SASL support: ${have_sasl} + Smartcard support: ${have_smartcard} + USB redirection support: ${have_usbredir} ${with_usbredir_hotplug} + DBus: ${have_dbus} + WebDAV support: ${have_phodav} + LZ4 support: ${enable_lz4} + + Now type 'make' to build $PACKAGE + +" >&5 +$as_echo "$as_me: + + Spice-Gtk $VERSION + ============== + + prefix: ${prefix} + c compiler: ${CC} + Target: ${red_target} + + Gtk: ${with_gtk} + Coroutine: ${with_coroutine} + PulseAudio: ${enable_pulse} + GStreamer Audio: ${have_gstaudio} + GStreamer Video: ${have_gstvideo} + SASL support: ${have_sasl} + Smartcard support: ${have_smartcard} + USB redirection support: ${have_usbredir} ${with_usbredir_hotplug} + DBus: ${have_dbus} + WebDAV support: ${have_phodav} + LZ4 support: ${enable_lz4} + + Now type 'make' to build $PACKAGE + +" >&6;} + + ac_save_IFS="$IFS" + IFS="|" + for msg in $spice_warnings; do + IFS="$ac_save_IFS" + if ${msg:+false} :; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg" >&5 +$as_echo "$as_me: WARNING: $msg" >&2;}; echo >&2 +fi + done + IFS="$ac_save_IFS" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6e65188 --- /dev/null +++ b/configure.ac @@ -0,0 +1,648 @@ +AC_PREREQ([2.57]) + +AC_INIT([spice-gtk], [m4_esyscmd(build-aux/git-version-gen .tarball-version)], + [spice-devel@lists.freedesktop.org]) + +AC_CONFIG_MACRO_DIR([m4]) +m4_include([spice-common/m4/spice-deps.m4]) +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_AUX_DIR([build-aux]) + +AM_INIT_AUTOMAKE([foreign dist-bzip2 -Wall -Werror -Wno-portability]) +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +LT_INIT([disable-static win32-dll]) +AM_MAINTAINER_MODE + +IT_PROG_INTLTOOL([0.40.0]) +GETTEXT_PACKAGE=spice-gtk +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],"$GETTEXT_PACKAGE", [GETTEXT package name]) +AM_GLIB_GNU_GETTEXT + + +SPICE_GTK_LOCALEDIR=[${datadir}/locale] +AC_SUBST(SPICE_GTK_LOCALEDIR) + +GTK_DOC_CHECK([1.14],[--flavour no-tmpl]) + +AC_PROG_CC +AC_PROG_CC_C99 +if test "x$ac_cv_prog_cc_c99" = xno; then + AC_MSG_ERROR([C99 compiler is required.]) +fi + + +AC_CHECK_PROG([STOW], [stow], [yes], [no]) +AS_IF([test "x$STOW" = "xyes" && test -d /usr/local/stow], [ + AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME} ***]) + ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}" +]) + +AC_PROG_INSTALL +AC_CANONICAL_HOST +AC_PROG_LIBTOOL +AM_PROG_CC_C_O +AC_C_BIGENDIAN +AC_PATH_PROGS(PYTHON, python2 python) +RRA_LD_VERSION_SCRIPT + +AC_MSG_CHECKING([for native Win32]) +case "$host_os" in + *mingw*|*cygwin*) + os_win32=yes + gio_os=gio-windows-2.0 + red_target=Windows + ;; + *) + os_win32=no + gio_os=gio-unix-2.0 + red_target=Unix + ;; +esac +AC_MSG_RESULT([$os_win32]) +AM_CONDITIONAL([OS_WIN32],[test "$os_win32" = "yes"]) + +AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h]) +AC_CHECK_HEADERS([termios.h]) + +AC_CHECK_LIBM +AC_SUBST(LIBM) + +AC_CONFIG_SUBDIRS([spice-common]) +PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 0.12.11]) + +COMMON_CFLAGS='-I ${top_srcdir}/spice-common/ ${SPICE_PROTOCOL_CFLAGS}' +AC_SUBST(COMMON_CFLAGS) + +SPICE_GTK_MAJOR_VERSION=`echo $PACKAGE_VERSION | cut -d. -f1` +SPICE_GTK_MINOR_VERSION=`echo $PACKAGE_VERSION | cut -d. -f2` +SPICE_GTK_MICRO_VERSION=`echo $PACKAGE_VERSION | cut -d. -f3 | cut -d- -f1` +AS_IF([test "x$SPICE_GTK_MICRO_VERSION" = "x"], [SPICE_GTK_MICRO_VERSION=0]) + +AC_SUBST(SPICE_GTK_MAJOR_VERSION) +AC_SUBST(SPICE_GTK_MINOR_VERSION) +AC_SUBST(SPICE_GTK_MICRO_VERSION) + +dnl ========================================================================= +dnl Chek optional features + +srcdir="$(dirname $0)" +if test ! -e "$srcdir/src/vncdisplaykeymap_osx2xtkbd.c"; then + AC_MSG_CHECKING([for Text::CSV Perl module]) + perl -MText::CSV -e "" >/dev/null 2>&1 + if test $? -ne 0 ; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Text::CSV Perl module is required to compile this package]) + fi + AC_MSG_RESULT([found]) +fi + +SPICE_GLIB_REQUIRES="" +SPICE_GTK_REQUIRES="" + +PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.17.7) +AC_SUBST(PIXMAN_CFLAGS) +AC_SUBST(PIXMAN_LIBS) +SPICE_GLIB_REQUIRES="${SPICE_GLIB_REQUIRES} pixman-1 >= 0.17.7" + +PKG_CHECK_MODULES(SSL, openssl) +AC_SUBST(SSL_CFLAGS) +AC_SUBST(SSL_LIBS) +SPICE_GLIB_REQUIRES="${SPICE_GLIB_REQUIRES} openssl" + +SPICE_CHECK_SASL + +AC_MSG_CHECKING([which gtk+ version to compile against]) +AC_ARG_WITH([gtk], + [AS_HELP_STRING([--with-gtk=@<:@3.0/no@:>@],[which gtk+ version to compile against @<:@default=3.0@:>@])], + [case "$with_gtk" in + 3.0) AC_MSG_RESULT([$with_gtk]) ;; + no) AC_MSG_RESULT([none]) ;; + *) AC_MSG_ERROR([invalid gtk version specified]) ;; + esac], + [with_gtk=3.0]) + +case "$with_gtk" in + 3.0) GTK_REQUIRED=3.12 + GTK_ENCODED_VERSION="GDK_VERSION_3_12" + ;; + no) + AS_IF([test x$enable_gtk_doc = xyes], + [AC_MSG_ERROR([Without GTK+, gtk-doc must be disabled])]) +esac + +AC_SUBST([GTK_REQUIRED]) +AM_CONDITIONAL([WITH_GTK],[test "$with_gtk" != "no"]) + +AS_IF([test "x$with_gtk" != "xno"], + [PKG_CHECK_MODULES(GTK, gtk+-3.0 >= $GTK_REQUIRED epoxy)] + [GTK_CFLAGS="$GTK_CFLAGS -DGDK_VERSION_MIN_REQUIRED=$GTK_ENCODED_VERSION \ + -DGDK_VERSION_MAX_ALLOWED=$GTK_ENCODED_VERSION"]) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) +SPICE_GTK_REQUIRES="${SPICE_GTK_REQUIRES} gtk+-3.0 >= $GTK_REQUIRED" + +# Check for gdk_event_get_scancode function +# This was added in Gdk 3.22 +# The check allows the usage of the function in case the function is +# backported or in case of compilation from Gdk master branch +old_LIBS="$LIBS" +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $GTK_CFLAGS" +LIBS="$LIBS $GTK_LIBS" +AC_CHECK_FUNCS(gdk_event_get_scancode) +LIBS="$old_LIBS" +CFLAGS="$old_CFLAGS" + +PKG_CHECK_EXISTS([gtk+-quartz-$with_gtk], [have_quartz=yes], [have_quartz=no]) +AS_IF([test "x$have_quartz" = "xyes"], [AC_DEFINE([HAVE_QUARTZ], 1, [Have Quartz?])]) +AM_CONDITIONAL([WITH_DISPLAY_QUARTZ], [test "x$have_quartz" = "xyes"]) + +PKG_CHECK_EXISTS([gtk+-win32-$with_gtk], [have_win32=yes], [have_win32=no]) +AS_IF([test "x$have_win32" = "xyes"], [AC_DEFINE([HAVE_WINDOWS], 1, [Have Win32?])]) +AM_CONDITIONAL([WITH_DISPLAY_WINDOWS], [test "x$have_win32" = "xyes"]) + +AC_CHECK_HEADERS([X11/XKBlib.h]) + +AC_ARG_WITH([pnp-ids-path], + AC_HELP_STRING([--with-pnp-ids-path], + [Specify the path to pnp.ids @<:@default=(internal)@:>@]), + [], + [with_pnp_ids_path="\${pnpdatadir}/pnp.ids"]) + +AM_CONDITIONAL(USE_INTERNAL_PNP_IDS, test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids") +PNP_IDS=$with_pnp_ids_path +AC_SUBST(PNP_IDS) +if test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids"; then + EXTERNAL_PNP_IDS="no (internal)" +else + EXTERNAL_PNP_IDS="$with_pnp_ids_path" +fi + +AC_CHECK_FUNCS(clearenv strtok_r) + +# Keep these two definitions in agreement. +GLIB2_REQUIRED="2.36" +GLIB2_ENCODED_VERSION="GLIB_VERSION_2_36" + +PKG_CHECK_MODULES(GLIB2, glib-2.0 >= $GLIB2_REQUIRED) +GLIB2_CFLAGS="$GLIB2_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=$GLIB2_ENCODED_VERSION \ + -DGLIB_VERSION_MAX_ALLOWED=$GLIB2_ENCODED_VERSION" +AC_SUBST(GLIB2_CFLAGS) +AC_SUBST(GLIB2_LIBS) + +PKG_CHECK_MODULES(GOBJECT2, gobject-2.0) +AC_SUBST(GOBJECT2_CFLAGS) +AC_SUBST(GOBJECT2_LIBS) + +PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.36 $gio_os) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) + +PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.0) +AC_SUBST(CAIRO_CFLAGS) +AC_SUBST(CAIRO_LIBS) + +PKG_CHECK_MODULES(GTHREAD, gthread-2.0) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + +AC_ARG_ENABLE([webdav], + AS_HELP_STRING([--enable-webdav=@<:@auto/yes/no@:>@], + [Enable webdav support @<:@default=auto@:>@]), + [], + [enable_webdav="auto"]) + +if test "x$enable_webdav" = "xno"; then + have_phodav="no" +else + PKG_CHECK_MODULES(PHODAV, [libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.49.91], [have_phodav=yes], [have_phodav=no]) + AC_SUBST(PHODAV_CFLAGS) + AC_SUBST(PHODAV_LIBS) + + if test "x$have_phodav" = "xno" && test "x$enable_webdav" = "xyes"; then + AC_MSG_ERROR([webdav support explicitly requested, but some required packages are not available]) + fi +fi +AS_IF([test "x$have_phodav" = "xyes"], + AC_DEFINE([USE_PHODAV], [1], [Define if supporting phodav])) + +AM_CONDITIONAL([WITH_PHODAV], [test "x$have_phodav" = "xyes"]) + +AC_ARG_WITH([audio], + AS_HELP_STRING([--with-audio=@<:@gstreamer/pulse/auto/no@:>@], [For legacy compatibility only]), + [SPICE_WARNING([--with-audio is deprecated. Use --enable-pulse and/or --enable-gstaudio instead]) + case "$with_audio" in + pulse) enable_pulse="yes"; enable_gstaudio="no" ;; + gstreamer) enable_pulse="no"; enable_gstaudio="yes" ;; + no) enable_pulse="no"; enable_gstaudio="no" ;; + esac +]) + +AC_ARG_ENABLE([pulse], + AS_HELP_STRING([--enable-pulse=@<:@yes/auto/no@:>@], [Enable the PulseAudio backend @<:@default=auto@:>@]), + [], + [enable_pulse="auto"]) +AS_IF([test "x$enable_pulse" != "xno"], + [PKG_CHECK_MODULES(PULSE, [libpulse libpulse-mainloop-glib], + [AC_DEFINE([HAVE_PULSE], 1, [Have PulseAudio support?]) + enable_pulse="yes"], + [AS_IF([test "x$enable_pulse" = "xyes"], + AC_MSG_ERROR([PulseAudio requested but not found])) + enable_pulse="no" + ]) +]) +AM_CONDITIONAL([HAVE_PULSE], [test "x$enable_pulse" = "xyes"]) +AC_SUBST(PULSE_CFLAGS) +AC_SUBST(PULSE_LIBS) + +AC_ARG_ENABLE([gstaudio], + AS_HELP_STRING([--enable-gstaudio=@<:@yes/auto/no@:>@], [Enable the GStreamer 1.0 audio backend @<:@default=auto@:>@]), + [], + [enable_gstaudio="auto"]) +AS_IF([test "x$enable_gstaudio" != "xno"], + [SPICE_CHECK_GSTREAMER(GSTAUDIO, 1.0, [gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-audio-1.0], + [SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 1.0], [audioconvert audioresample appsink]) + SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 1.0], [autoaudiosrc]) + AS_IF([test x"$missing_gstreamer_elements" = "xyes"], + SPICE_WARNING([The GStreamer 1.0 audio backend can be built but may not work.])) + ], + [AS_IF([test "x$enable_gstaudio" = "xyes"], + AC_MSG_ERROR([GStreamer 1.0 audio requested but not found])) + ]) + ], [have_gstaudio="no"] +) +AM_CONDITIONAL([HAVE_GSTAUDIO], [test "x$have_gstaudio" = "xyes"]) + +AS_IF([test "x$enable_pulse$have_gstaudio" = "xnono"], + [SPICE_WARNING([No PulseAudio or GStreamer 1.0 audio decoder, audio will not be streamed]) +]) + +AC_ARG_ENABLE([gstvideo], + AS_HELP_STRING([--enable-gstvideo=@<:@auto/yes/no@:>@], + [Enable GStreamer video support @<:@default=auto@:>@]), + [], + [enable_gstvideo="auto"]) +AS_IF([test "x$enable_gstvideo" != "xno"], + [SPICE_CHECK_GSTREAMER(GSTVIDEO, 1.0, + [gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0], + [missing_gstreamer_elements="" + SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 1.0], [appsrc videoconvert appsink]) + SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 1.0], [jpegdec vp8dec]) + SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-bad 1.0], [h264parse]) + SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gstreamer-libav 1.0], [avdec_h264]) + AS_IF([test x"$missing_gstreamer_elements" = "xyes"], + SPICE_WARNING([The GStreamer video decoder can be built but may not work.])) + ], + [AS_IF([test "x$enable_gstvideo" = "xyes"], + AC_MSG_ERROR([GStreamer 1.0 video requested but not found])) + ]) + ], [have_gstvideo="no"] +) +AM_CONDITIONAL([HAVE_GSTVIDEO], [test "x$have_gstvideo" = "xyes"]) + +AC_ARG_ENABLE([builtin-mjpeg], + AS_HELP_STRING([--enable-builtin-mjpeg], [Enable the builtin mjpeg video decoder @<:@default=yes@:>@]), + [], + enable_builtin_mjpeg="yes") +AS_IF([test "x$enable_builtin_mjpeg" = "xyes"], + [AC_DEFINE([HAVE_BUILTIN_MJPEG], 1, [Use the builtin mjpeg decoder?])]) +AM_CONDITIONAL(HAVE_BUILTIN_MJPEG, [test "x$enable_builtin_mjpeg" != "xno"]) + +AS_IF([test "x$enable_builtin_mjpeg$enable_gstvideo" = "xnono"], + [SPICE_WARNING([No builtin MJPEG or GStreamer decoder, video will not be streamed])]) + +AC_CHECK_LIB(jpeg, jpeg_destroy_decompress, + AC_MSG_CHECKING([for jpeglib.h]) + AC_TRY_CPP( +[#include <stdio.h> +#undef PACKAGE +#undef VERSION +#undef HAVE_STDLIB_H +#include <jpeglib.h>], + JPEG_LIBS='-ljpeg' + AC_MSG_RESULT($jpeg_ok), + AC_MSG_ERROR([jpeglib.h not found])), + AC_MSG_ERROR([libjpeg not found])) +AC_SUBST(JPEG_LIBS) + +AC_CHECK_LIB(z, deflate, Z_LIBS='-lz', AC_MSG_ERROR([zlib not found])) +AC_SUBST(Z_LIBS) + +SPICE_CHECK_SMARTCARD +AM_CONDITIONAL([WITH_SMARTCARD], [test "x$have_smartcard" = "xyes"]) + +AC_ARG_ENABLE([usbredir], + AS_HELP_STRING([--enable-usbredir=@<:@auto/yes/no@:>@], + [Enable usbredir support @<:@default=auto@:>@]), + [], + [enable_usbredir="auto"]) + +if test "x$enable_usbredir" = "xno"; then + have_usbredir="no" +else + if ${PKG_CONFIG} libusbredirparser-0.5; then + PKG_CHECK_MODULES([USBREDIR], + [libusb-1.0 >= 1.0.9 libusbredirhost libusbredirparser-0.5], + [have_usbredir=yes], + [have_usbredir=no]) + else + PKG_CHECK_MODULES([USBREDIR], + [libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4.2 libusbredirparser >= 0.4], + [have_usbredir=yes], + [have_usbredir=no]) + fi + if test "x$have_usbredir" = "xno" && test "x$enable_usbredir" = "xyes"; then + AC_MSG_ERROR([usbredir support explicitly requested, but some required packages are not available]) + fi + + # On non windows we need either libusb hotplug support or gudev + if test "x$have_usbredir" = "xyes" && test "x$os_win32" = "xno"; then + PKG_CHECK_MODULES([LIBUSB_HOTPLUG], [libusb-1.0 >= 1.0.16], + [have_libusb_hotplug=yes], [have_libusb_hotplug=no]) + if test "x$have_libusb_hotplug" = "xyes"; then + AC_DEFINE([USE_LIBUSB_HOTPLUG], [1], [Define if libusb has hotplug support]) + with_usbredir_hotplug="with libusb hotplug" + else + PKG_CHECK_MODULES([GUDEV], + [gudev-1.0], + [have_gudev=yes], + [have_gudev=no]) + + if test "x$have_gudev" = "xno" && test "x$enable_usbredir" = "xyes"; then + AC_MSG_ERROR([usbredir requested but required gudev is not available]) + fi + if test "x$have_gudev" = "xyes"; then + AC_DEFINE([USE_GUDEV], [1], [Define if supporting gudev]) + with_usbredir_hotplug="with gudev hotplug" + else + have_usbredir=no + fi + fi + fi + + if test "x$have_usbredir" = "xyes"; then + AC_DEFINE([USE_USBREDIR], [1], [Define if supporting usbredir proxying]) + fi +fi +AM_CONDITIONAL([WITH_USBREDIR], [test "x$have_usbredir" = "xyes"]) + +AC_ARG_ENABLE([polkit], + AS_HELP_STRING([--enable-polkit=@<:@auto/yes/no@:>@], + [Enable PolicyKit support (for the usb acl helper)@<:@default=auto@:>@]), + [], + [enable_polkit="auto"]) + +if test "x$have_usbredir" = "xyes" && test "x$enable_polkit" != "xno"; then + PKG_CHECK_MODULES([POLKIT], [polkit-gobject-1 >= 0.96], + [have_polkit=yes], + [have_polkit=no]) + AC_CHECK_HEADER([acl/libacl.h], [], [have_polkit=no]) + AC_CHECK_LIB([acl], [acl_get_file], [ACL_LIBS=-lacl], [have_polkit=no]) + if test "x$enable_polkit" = "xyes" && test "x$have_polkit" = "xno"; then + AC_MSG_ERROR([PolicyKit support explicitly requested, but some required packages are not available]) + fi + + if test "x$have_polkit" = "xyes"; then + AC_SUBST(ACL_LIBS) + AC_DEFINE([USE_POLKIT], [1], [Define if supporting polkit]) + fi + AM_CONDITIONAL([WITH_POLKIT], [test "x$have_polkit" = "xyes"]) + POLICYDIR=`${PKG_CONFIG} polkit-gobject-1 --variable=policydir` + AC_SUBST(POLICYDIR) + # Check for polkit_authority_get_sync() + AC_CHECK_LIB([polkit-gobject-1], [polkit_authority_get_sync], ac_have_pk_auth_get_sync="1", ac_have_pk_auth_get_sync="0") + AC_DEFINE_UNQUOTED([HAVE_POLKIT_AUTHORITY_GET_SYNC], $ac_have_pk_auth_get_sync, [Define if you have a polkit with polkit_authority_get_sync()]) + AC_CHECK_LIB([polkit-gobject-1], [polkit_authorization_result_get_dismissed], ac_have_pk_authorization_result_get_dismissed="1", ac_have_pk_authorization_result_get_dismissed="0") + AC_DEFINE_UNQUOTED([HAVE_POLKIT_AUTHORIZATION_RESULT_GET_DISMISSED], $ac_have_pk_authorization_result_get_dismissed, [Define if you have a polkit with polkit_authorization_result_get_dismissed()]) +else + AM_CONDITIONAL(WITH_POLKIT, false) +fi + +if test "x$have_usbredir" = "xyes" && test "x$have_polkit" != "xyes"; then + AC_MSG_WARN([Building with usbredir support, but *not* building the usb acl helper]) +fi + +AC_ARG_ENABLE([pie], + AS_HELP_STRING([--enable-pie=@<:@auto/yes/no@:>@], + [Enable position-independent-executable support (for the usb acl helper)@<:@default=auto@:>@]), + [], + [enable_pie="auto"]) + +if test "x$have_polkit" = "xyes" && test "x$enable_pie" != "xno"; then + save_CFLAGS="$CFLAGS" + save_LDFLAGS="$LDFLAGS" + CFLAGS="$CFLAGS -fPIE" + LDFLAGS="$LDFLAGS -pie -Wl,-z,relro -Wl,-z,now" + AC_MSG_CHECKING([for PIE support]) + AC_LINK_IFELSE([AC_LANG_SOURCE([void main () {}])], + [have_pie=yes], + [have_pie=no]) + AC_MSG_RESULT([$have_pie]) + if test "x$have_pie" = "xno" && test "x$enable_pie" = "xyes"; then + AC_MSG_ERROR([pie support explicitly requested, but your toolchain does not support it]) + fi + if test "x$have_pie" = "xyes"; then + PIE_CFLAGS="-fPIE" + PIE_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" + AC_SUBST(PIE_CFLAGS) + AC_SUBST(PIE_LDFLAGS) + fi + CFLAGS="$save_CFLAGS" + LDFLAGS="$save_LDFLAGS" +fi + +AC_ARG_WITH([usb-acl-helper-dir], + AS_HELP_STRING([--with-usb-acl-helper-dir=DIR], + [Directory where the USB ACL helper binary should be installed]), + [ACL_HELPER_DIR="$with_usb_acl_helper_dir"], + [ACL_HELPER_DIR="${bindir}/"]) +AC_SUBST([ACL_HELPER_DIR]) + +AC_ARG_WITH([usb-ids-path], + AC_HELP_STRING([--with-usb-ids-path], + [Specify the path to usb.ids @<:@default=auto@:>@]), + [USB_IDS="$with_usb_ids_path"], + [USB_IDS="auto"]) +AC_MSG_CHECKING([for usb.ids]) +if test "x$USB_IDS" = "xauto"; then + if test -n "$PKG_CONFIG"; then + USB_IDS=$($PKG_CONFIG --variable=usbids usbutils) + else + USB_IDS= + fi +fi +if test -n "$USB_IDS"; then + AC_MSG_RESULT([$USB_IDS]) + AC_SUBST(USB_IDS) + AC_DEFINE([WITH_USBIDS], [1], [Define if compiling with usb.ids support]) +else + AC_MSG_RESULT([not found]) +fi + +AC_ARG_WITH([coroutine], + AS_HELP_STRING([--with-coroutine=@<:@ucontext/gthread/winfiber/auto@:>@], + [use ucontext or GThread for coroutines @<:@default=auto@:>@]), + [], + [with_coroutine=auto]) + +case $with_coroutine in + ucontext|gthread|winfiber|auto) ;; + *) AC_MSG_ERROR(Unsupported coroutine type) +esac + +if test "$with_coroutine" = "auto"; then + if test "$os_win32" = "yes"; then + with_coroutine=winfiber + else + with_coroutine=ucontext + fi +fi + +if test "$with_coroutine" = "ucontext"; then + AC_CHECK_FUNC(makecontext, [],[with_coroutine=gthread]) + AC_CHECK_FUNC(swapcontext, [],[with_coroutine=gthread]) + AC_CHECK_FUNC(getcontext, [],[with_coroutine=gthread]) +fi + +WITH_UCONTEXT=0 +WITH_GTHREAD=0 +WITH_WINFIBER=0 + +case $with_coroutine in + ucontext) WITH_UCONTEXT=1 ;; + gthread) WITH_GTHREAD=1 ;; + winfiber) WITH_WINFIBER=1 ;; + *) AC_MSG_ERROR(Unsupported coroutine type) +esac + +AC_DEFINE_UNQUOTED([WITH_UCONTEXT],[$WITH_UCONTEXT], [Whether to use ucontext coroutine impl]) +AM_CONDITIONAL(WITH_UCONTEXT, [test "x$WITH_UCONTEXT" = "x1"]) + +AC_DEFINE_UNQUOTED([WITH_WINFIBER],[$WITH_WINFIBER], [Whether to use fiber coroutine impl]) +AM_CONDITIONAL(WITH_WINFIBER, [test "x$WITH_WINFIBER" = "x1"]) + +AC_DEFINE_UNQUOTED([WITH_GTHREAD],[$WITH_GTHREAD], [Whether to use gthread coroutine impl]) +AM_CONDITIONAL(WITH_GTHREAD, [test "x$WITH_GTHREAD" = "x1"]) + +AM_CONDITIONAL([HAVE_INTROSPECTION], [test "0" = "1"]) +m4_ifdef([GOBJECT_INTROSPECTION_CHECK],[ + PKG_CHECK_EXISTS([GOBJECT_INTROSPECTION], + [gobject-introspection-1.0 >= 0.9.4], + [has_symbol_prefix=yes], [:]) + GOBJECT_INTROSPECTION_CHECK([0.6.7]) +]) +AM_CONDITIONAL([G_IR_SCANNER_SYMBOL_PREFIX], [test "x$has_symbol_prefix" = "xyes"]) + +AC_ARG_ENABLE([controller], + AS_HELP_STRING([--enable-controller], [Enable controller build @<:@default=yes@:>@]), + [], + enable_controller="yes") + +AM_CONDITIONAL(WITH_CONTROLLER, [test "x$enable_controller" != "xno"]) + +AC_ARG_ENABLE([vala], + AS_HELP_STRING([--enable-vala], [Check for vala requirements @<:@default=no@:>@]), + [], + enable_vala="no") + +VALA_REQUIRED=0.14 +if test x$enable_vala = xyes ; then + # check for vala + AM_PROG_VALAC([$VALA_REQUIRED]) + AC_PATH_PROG(VAPIGEN, vapigen, no) + if test "x$VAPIGEN" == "xno"; then + AC_MSG_ERROR([Cannot find the "vapigen" binary in your PATH]) + fi + AC_SUBST(VAPIGEN) +fi + +AM_CONDITIONAL(WITH_VALA, [test "x$enable_vala" = "xyes"]) + +VAPIDIR="${datadir}/vala/vapi" +AC_SUBST(VAPIDIR) + +AC_ARG_ENABLE([dbus], + AS_HELP_STRING([--enable-dbus=@<:@auto/yes/no@:>@], + [Enable dbus support for desktop integration (disabling automount) @<:@default=auto@:>@]), + [], + [enable_dbus="auto"]) + +have_dbus=no +if test "x$enable_dbus" != "xno"; then + AC_DEFINE([USE_GDBUS], [1], [Define if supporting gdbus]) + have_dbus=yes +else + SPICE_WARNING([No D-Bus support, desktop integration and USB redirection may not work properly]) +fi + +SPICE_CHECK_LZ4 + +dnl =========================================================================== +dnl check compiler flags + +# some glib/gstreamer enums use 1 << 31 +dontwarn="-Wshift-overflow=2" + +SPICE_COMPILE_WARNINGS([$dontwarn]) + +SPICE_CFLAGS="$SPICE_CFLAGS $WARN_CFLAGS" + +AC_SUBST(SPICE_CFLAGS) + +SPICE_GLIB_CFLAGS="$PIXMAN_CFLAGS $PULSE_CFLAGS $GSTAUDIO_CFLAGS $GSTVIDEO_CFLAGS $GLIB2_CFLAGS $GIO_CFLAGS $GOBJECT2_CFLAGS $SSL_CFLAGS $SASL_CFLAGS" +SPICE_GTK_CFLAGS="$SPICE_GLIB_CFLAGS $GTK_CFLAGS " + +AC_SUBST(SPICE_GLIB_CFLAGS) +AC_SUBST(SPICE_GTK_CFLAGS) + +AC_SUBST(SPICE_GLIB_REQUIRES) +AC_SUBST(SPICE_GTK_REQUIRES) + +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AM_CONDITIONAL([BUILD_TESTS], [test x"$enable_static" = xyes]) + +AC_OUTPUT([ +Makefile +spice-client-glib-2.0.pc +spice-client-gtk-3.0.pc +spice-controller.pc +data/Makefile +po/Makefile.in +src/Makefile +src/spice-version.h +src/controller/Makefile +doc/Makefile +doc/reference/Makefile +man/Makefile +vapi/Makefile +tests/Makefile +]) + +dnl ========================================================================== +AC_MSG_NOTICE([ + + Spice-Gtk $VERSION + ============== + + prefix: ${prefix} + c compiler: ${CC} + Target: ${red_target} + + Gtk: ${with_gtk} + Coroutine: ${with_coroutine} + PulseAudio: ${enable_pulse} + GStreamer Audio: ${have_gstaudio} + GStreamer Video: ${have_gstvideo} + SASL support: ${have_sasl} + Smartcard support: ${have_smartcard} + USB redirection support: ${have_usbredir} ${with_usbredir_hotplug} + DBus: ${have_dbus} + WebDAV support: ${have_phodav} + LZ4 support: ${enable_lz4} + + Now type 'make' to build $PACKAGE + +]) +SPICE_PRINT_MESSAGES diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..06592de --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,14 @@ +NULL= + +EXTRA_DIST = \ + spice-protocol.vapi \ + org.spice-space.lowlevelusbaccess.policy \ + $(NULL) + +vapidir = $(VAPIDIR) +vapi_DATA = spice-protocol.vapi + +policydir = $(POLICYDIR) +policy_DATA = org.spice-space.lowlevelusbaccess.policy + +-include $(top_srcdir)/git.mk diff --git a/data/Makefile.in b/data/Makefile.in new file mode 100644 index 0000000..82da4e5 --- /dev/null +++ b/data/Makefile.in @@ -0,0 +1,648 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(policydir)" "$(DESTDIR)$(vapidir)" +DATA = $(policy_DATA) $(vapi_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = \ + spice-protocol.vapi \ + org.spice-space.lowlevelusbaccess.policy \ + $(NULL) + +vapidir = $(VAPIDIR) +vapi_DATA = spice-protocol.vapi +policydir = $(POLICYDIR) +policy_DATA = org.spice-space.lowlevelusbaccess.policy +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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-policyDATA: $(policy_DATA) + @$(NORMAL_INSTALL) + @list='$(policy_DATA)'; test -n "$(policydir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(policydir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(policydir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(policydir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(policydir)" || exit $$?; \ + done + +uninstall-policyDATA: + @$(NORMAL_UNINSTALL) + @list='$(policy_DATA)'; test -n "$(policydir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(policydir)'; $(am__uninstall_files_from_dir) +install-vapiDATA: $(vapi_DATA) + @$(NORMAL_INSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(vapidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(vapidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(vapidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(vapidir)" || exit $$?; \ + done + +uninstall-vapiDATA: + @$(NORMAL_UNINSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(vapidir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(policydir)" "$(DESTDIR)$(vapidir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-policyDATA install-vapiDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -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-policyDATA uninstall-vapiDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-policyDATA install-ps \ + install-ps-am install-strip install-vapiDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-policyDATA uninstall-vapiDATA + +.PRECIOUS: Makefile + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/data/org.spice-space.lowlevelusbaccess.policy b/data/org.spice-space.lowlevelusbaccess.policy new file mode 100644 index 0000000..535ee31 --- /dev/null +++ b/data/org.spice-space.lowlevelusbaccess.policy @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE policyconfig PUBLIC + "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> +<policyconfig> + + <vendor>The Spice Project</vendor> + <vendor_url>http://spice-space.org/</vendor_url> + <icon_name>spice</icon_name> + + <action id="org.spice-space.lowlevelusbaccess"> + <description>Low level USB device access</description> + <message>Privileges are required for low level USB device access (for usb device pass through).</message> + <defaults> + <allow_inactive>no</allow_inactive> + <allow_active>yes</allow_active> + </defaults> + </action> + +</policyconfig> diff --git a/data/spice-protocol.vapi b/data/spice-protocol.vapi new file mode 100644 index 0000000..cca03ed --- /dev/null +++ b/data/spice-protocol.vapi @@ -0,0 +1,210 @@ +namespace SpiceProtocol { + [CCode (cprefix = "Controller", cheader_filename = "spice/controller_prot.h")] + namespace Controller { + [CCode (cname = "CONTROLLER_MAGIC")] + public const uint32 MAGIC; + [CCode (cname = "CONTROLLER_VERSION")] + public const int VERSION; + + [Compact] + public struct InitHeader { + uint32 magic; + uint32 version; + uint32 size; + } + + [Compact] + public struct Init { + InitHeader base; + uint64 credentials; + uint32 flags; + } + + [CCode (cprefix = "CONTROLLER_FLAG_")] + [Flags] + public enum Flag { + EXCLUSIVE, + } + + [Compact] + public struct Msg { + uint32 id; + uint32 size; + } + + [CCode (cprefix = "CONTROLLER_")] + public enum MsgId { + //external app -> spice client + HOST, + PORT, + SPORT, + PASSWORD, + + SECURE_CHANNELS, + DISABLE_CHANNELS, + + TLS_CIPHERS, + CA_FILE, + HOST_SUBJECT, + + FULL_SCREEN, + SET_TITLE, + + CREATE_MENU, + DELETE_MENU, + + HOTKEYS, + SEND_CAD, + + CONNECT, + SHOW, + HIDE, + + ENABLE_SMARTCARD, + + ENABLE_USB, + ENABLE_USB_AUTOSHARE, + USB_FILTER, + + PROXY, + + //spice client -> external app + MENU_ITEM_CLICK, + + COLOR_DEPTH, + DISABLE_EFFECTS, + } + + [CCode (cname = "unsigned int", cprefix = "CONTROLLER_", has_type_id = false)] + [Flags] + public enum Display { + SET_FULL_SCREEN, + AUTO_DISPLAY_RES, + } + + [Compact] + [CCode (cname = "ControllerValue")] + public struct MsgValue: Msg { + Msg base; + uint32 value; + } + + [Compact] + [CCode (cname = "ControllerData")] + public struct MsgData { + Msg base; + uint8 data[0]; + } + + [CCode (cname = "CONTROLLER_MENU_ITEM_DELIMITER")] + public static string MENU_ITEM_DELIMITER; + [CCode (cname = "CONTROLLER_MENU_PARAM_DELIMITER")] + public static string MENU_PARAM_DELIMITER; + + [CCode (cname = "SPICE_MENU_INTERNAL_ID_BASE")] + public static int MENU_INTERNAL_ID_BASE; + [CCode (cname = "SPICE_MENU_INTERNAL_ID_SHIFT")] + public static int MENU_INTERNAL_ID_SHIFT; + + [CCode (cprefix = "CONTROLLER_MENU_FLAGS_", cname = "unsigned int", has_type_id = false)] + [Flags] + public enum MenuFlags { + SEPARATOR, + DISABLED, + POPUP, + CHECKED, + GRAYED, + } + } + + [CCode (cprefix = "FrgMenu", cheader_filename = "spice/foreign_menu_prot.h")] + namespace ForeignMenu { + [CCode (cname = "FOREIGN_MENU_MAGIC")] + public const uint32 MAGIC; + [CCode (cname = "FOREIGN_MENU_VERSION")] + public const int VERSION; + + [Compact] + public struct InitHeader { + uint32 magic; + uint32 version; + uint32 size; + } + + [Compact] + [CCode (has_destroy_function = false)] + public struct Init { + InitHeader base; + uint64 credentials; + string title; // utf8 + } + + [Compact] + public struct Msg { + uint32 id; + uint32 size; + } + + [CCode (cprefix = "FOREIGN_MENU_", cname = "int")] + public enum MsgId { + //external app -> spice client + SET_TITLE, + ADD_ITEM, + MODIFY_ITEM, + REMOVE_ITEM, + CLEAR, + + //spice client -> external app + ITEM_EVENT, + APP_ACTIVATED, + APP_DEACTIVATED, + } + + [Compact] + [CCode (cname = "FrgMenuSetTitle")] + public struct SetTitle { + Msg base; + string string; // utf8 + } + + [CCode (cprefix = "FOREIGN_MENU_ITEM_TYPE_", cname = "unsigned int", has_type_id = false)] + [Flags] + public enum MenuFlags { + CHECKED, + DIM, + SEPARATOR + } + + [Compact] + [CCode (cname = "FrgMenuAddItem")] + public struct AddItem { + Msg base; + uint32 id; + uint32 type; + uint32 position; + string string; // utf8 + } + + [Compact] + [CCode (cname = "FrgMenuRmItem")] + public struct RmItem { + Msg base; + uint32 id; + } + + [CCode (cprefix = "FOREIGN_MENU_EVENT_", cname = "int")] + public enum EventType { + CLICK, + CHECKED, + UNCHECKED, + } + + [Compact] + [CCode (cname = "FrgMenuEvent")] + public struct Event { + Msg base; + uint32 id; + uint32 action; + } + } +} diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..034926c --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = reference + +-include $(top_srcdir)/git.mk diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..85dafe7 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,743 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = reference +all: all-recursive + +.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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am new file mode 100644 index 0000000..29f31fc --- /dev/null +++ b/doc/reference/Makefile.am @@ -0,0 +1,81 @@ +NULL = + +AUTOMAKE_OPTIONS = 1.6 +DOC_MODULE = spice-gtk + +# The top-level SGML file +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml + +# Source code location +DOC_SOURCE_DIR = $(top_srcdir)/src + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS = \ + --deprecated-guards="SPICE_DISABLE_DEPRECATED" \ + --ignore-decorators="G_GNUC_INTERNAL" + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --xml-mode --output-format=xml + +# Used for dependencies. The docs will be rebuilt if any of these change. +HFILE_GLOB = $(top_srcdir)/src/*.h +CFILE_GLOB = $(top_srcdir)/src/*.c + +# Header files to ignore when scanning. Use base file name, no paths +IGNORE_HFILES= \ + bio-gio.h \ + channel-display-priv.h \ + channel-usbredir-priv.h \ + client_sw_canvas.h \ + continuation.h \ + controller \ + coroutine.h \ + decode.h \ + desktop-integration.h \ + display \ + gio-coroutine.h \ + giopipe.h \ + smartcard-manager-priv.h \ + spice-audio-priv.h \ + spice-channel-cache.h \ + spice-channel-priv.h \ + spice-cmdline.h \ + spice-common.h \ + spice-grab-sequence-prive.h \ + spice-gstaudio.h \ + spice-gtk-session-priv.h \ + spice-marshal.h \ + spice-pulse.h \ + spice-session-priv.h \ + spice-uri-priv.h \ + spice-util-priv.h \ + spice-widget-priv.h \ + spicy-connect.h \ + usb-acl-helper.h \ + usb-device-manager-priv.h \ + usbdk_api.h \ + usbutil.h \ + vmcstream.h \ + vncdisplaykeymap.h \ + win-usb-clerk.h \ + win-usb-dev.h \ + win-usb-driver-install.h \ + wocky-http-proxy.h \ + $(NULL) + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/src -I$(top_builddir)/src $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS) $(COMMON_CFLAGS) -DSPICE_COMPILATION +GTKDOC_LIBS = $(top_builddir)/src/libspice-client-glib-2.0.la $(top_builddir)/src/libspice-client-gtk-3.0.la $(GTK_LIBS) + +include $(top_srcdir)/gtk-doc.make + +# Comment this out if you want 'make check' to test you doc status +# and run some sanity checks +if ENABLE_GTK_DOC +TESTS_ENVIRONMENT = cd $(srcdir) && \ + DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ + SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) +#TESTS = $(GTKDOC_CHECK) +endif + +-include $(top_srcdir)/git.mk diff --git a/doc/reference/Makefile.in b/doc/reference/Makefile.in new file mode 100644 index 0000000..df8c0e8 --- /dev/null +++ b/doc/reference/Makefile.in @@ -0,0 +1,927 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# -*- mode: makefile -*- + +#################################### +# Everything below here is generic # +#################################### +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/reference +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +AUTOMAKE_OPTIONS = 1.6 +DOC_MODULE = spice-gtk + +# The top-level SGML file +DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml + +# Source code location +DOC_SOURCE_DIR = $(top_srcdir)/src + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS = \ + --deprecated-guards="SPICE_DISABLE_DEPRECATED" \ + --ignore-decorators="G_GNUC_INTERNAL" + + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS = --xml-mode --output-format=xml + +# Used for dependencies. The docs will be rebuilt if any of these change. +HFILE_GLOB = $(top_srcdir)/src/*.h +CFILE_GLOB = $(top_srcdir)/src/*.c + +# Header files to ignore when scanning. Use base file name, no paths +IGNORE_HFILES = \ + bio-gio.h \ + channel-display-priv.h \ + channel-usbredir-priv.h \ + client_sw_canvas.h \ + continuation.h \ + controller \ + coroutine.h \ + decode.h \ + desktop-integration.h \ + display \ + gio-coroutine.h \ + giopipe.h \ + smartcard-manager-priv.h \ + spice-audio-priv.h \ + spice-channel-cache.h \ + spice-channel-priv.h \ + spice-cmdline.h \ + spice-common.h \ + spice-grab-sequence-prive.h \ + spice-gstaudio.h \ + spice-gtk-session-priv.h \ + spice-marshal.h \ + spice-pulse.h \ + spice-session-priv.h \ + spice-uri-priv.h \ + spice-util-priv.h \ + spice-widget-priv.h \ + spicy-connect.h \ + usb-acl-helper.h \ + usb-device-manager-priv.h \ + usbdk_api.h \ + usbutil.h \ + vmcstream.h \ + vncdisplaykeymap.h \ + win-usb-clerk.h \ + win-usb-dev.h \ + win-usb-driver-install.h \ + wocky-http-proxy.h \ + $(NULL) + + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/src -I$(top_builddir)/src $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS) $(COMMON_CFLAGS) -DSPICE_COMPILATION +GTKDOC_LIBS = $(top_builddir)/src/libspice-client-glib-2.0.la $(top_builddir)/src/libspice-client-gtk-3.0.la $(GTK_LIBS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = +@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) +TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) +SETUP_FILES = \ + $(content_files) \ + $(expand_content_files) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt + +EXTRA_DIST = \ + $(HTML_IMAGES) \ + $(SETUP_FILES) + +DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ + html-build.stamp pdf-build.stamp \ + sgml.stamp html.stamp pdf.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test +@GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = +@GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp +@GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = +@GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp + +#### setup #### +GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) +GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; + +#### scan #### +GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) +GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; +GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) +GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; + +#### xml #### +GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) +GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XML_0 = @echo " DOC Building XML"; + +#### html #### +GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) +GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; +GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) +GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; + +#### pdf #### +GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) +GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; + +# Comment this out if you want 'make check' to test you doc status +# and run some sanity checks +@ENABLE_GTK_DOC_TRUE@TESTS_ENVIRONMENT = cd $(srcdir) && \ +@ENABLE_GTK_DOC_TRUE@ DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ +@ENABLE_GTK_DOC_TRUE@ SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/reference/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/reference/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_srcdir)/gtk-doc.make $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +@ENABLE_GTK_DOC_FALSE@all-local: +all-am: Makefile all-local +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am dist-hook \ + distclean distclean-generic distclean-libtool distclean-local \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-local + +.PRECIOUS: Makefile + + +gtkdoc-check.test: Makefile + $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ + echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ + chmod +x $@ + +all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) +.PHONY: all-gtk-doc + +@ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc + +docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) + +$(REPORT_FILES): sgml-build.stamp + +setup-build.stamp: + -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + destdir=`dirname $(abs_builddir)/$$file`; \ + test -d "$$destdir" || mkdir -p "$$destdir"; \ + test -f $(abs_srcdir)/$$file && \ + cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ + done; \ + fi; \ + fi + $(AM_V_at)touch setup-build.stamp + +scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) + $(GTK_DOC_V_SCAN)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) + $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + $(AM_V_at)touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent + $(GTK_DOC_V_XML)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) + $(AM_V_at)touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +xml/gtkdocentities.ent: Makefile + $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ + echo "<!ENTITY package \"$(PACKAGE)\">"; \ + echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \ + echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \ + echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \ + echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \ + echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \ + echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \ + ) > $@ + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$$?" = "0"; then \ + mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + -@test "x$(HTML_IMAGES)" = "x" || \ + for file in $(HTML_IMAGES) ; do \ + if test -f $(abs_srcdir)/$$file ; then \ + cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ + fi; \ + if test -f $(abs_builddir)/$$file ; then \ + cp $(abs_builddir)/$$file $(abs_builddir)/html; \ + fi; \ + done; + $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + $(AM_V_at)touch html-build.stamp + +pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ + mkpdf_options=""; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkpdf_options="$$mkpdf_options --verbose"; \ + fi; \ + fi; \ + if test "x$(HTML_IMAGES)" != "x"; then \ + for img in $(HTML_IMAGES); do \ + part=`dirname $$img`; \ + echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + if test $$? != 0; then \ + mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ + fi; \ + done; \ + fi; \ + gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) + $(AM_V_at)touch pdf-build.stamp + +############## + +clean-local: + @rm -f *~ *.bak + @rm -rf .libs + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + rm -f $(DOC_MODULE).types; \ + fi + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + rm -f $(DOC_MODULE)-sections.txt; \ + fi + +distclean-local: + @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ + fi + +maintainer-clean-local: + @rm -rf xml html + +install-data-local: + @installfiles=`echo $(builddir)/html/*`; \ + if test "$$installfiles" = '$(builddir)/html/*'; \ + then echo 1>&2 'Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo ' $(INSTALL_DATA) '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ + fi + +uninstall-local: + @if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +@HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs +@HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: +@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" +@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" +@HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" +@HAVE_GTK_DOC_FALSE@ @false + +dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local + @mkdir $(distdir)/html + @cp ./html/* $(distdir)/html + @-cp ./$(DOC_MODULE).pdf $(distdir)/ + @-cp ./$(DOC_MODULE).types $(distdir)/ + @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ + @cd $(distdir) && rm -f $(DISTCLEANFILES) + @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs +#TESTS = $(GTKDOC_CHECK) + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/reference/html/SpiceAudio.html b/doc/reference/html/SpiceAudio.html new file mode 100644 index 0000000..e3e3e5e --- /dev/null +++ b/doc/reference/html/SpiceAudio.html @@ -0,0 +1,273 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Spice Audio: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice Audio

+

Spice Audio — a helper to play and to record audio channels

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + +
+SpiceAudio * + +spice_audio_get () +
+SpiceAudio * + +spice_audio_new () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+GMainContext *main-contextRead / Write / Construct Only
+SpiceSession *sessionRead / Write / Construct Only
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceAudio
structSpiceAudioClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceAudio
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

A class that handles the playback and record channels for your +application, and connect them to the default sound system.

+
+
+

Functions

+
+

spice_audio_get ()

+
SpiceAudio *
+spice_audio_get (SpiceSession *session,
+                 GMainContext *context);
+

Gets the SpiceAudio associated with the passed in SpiceSession. +A new SpiceAudio instance will be created the first time this +function is called for a certain SpiceSession.

+

Note that this function returns a weak reference, which should not be used +after the SpiceSession itself has been unref-ed by the caller.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

the SpiceSession to connect to

 

context

a GMainContext to attach to (or NULL for default).

[allow-none]
+
+
+

Returns

+

a weak reference to a SpiceAudio +instance or NULL if failed.

+

[transfer none]

+
+
+
+
+

spice_audio_new ()

+
SpiceAudio *
+spice_audio_new (SpiceSession *session,
+                 GMainContext *context,
+                 const char *name);
+
+

spice_audio_new has been deprecated since version 0.8 and should not be used in newly-written code.

+

Use spice_audio_get() instead

+
+

Once instantiated, SpiceAudio will handle the playback and record +channels to stream to your local audio system.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the SpiceSession to connect to

 

context

a GMainContext to attach to (or NULL for +default).

[allow-none]

name

a name for the audio channels (or NULL for +application name).

[allow-none]
+
+
+

Returns

+

a new SpiceAudio instance or NULL if no backend or failed.

+
+
+
+
+

Types and Values

+
+

struct SpiceAudio

+
struct SpiceAudio;
+

The SpiceAudio struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceAudioClass

+
struct SpiceAudioClass {
+    GObjectClass parent_class;
+};
+
+

Class structure for SpiceAudio.

+
+

Members

+
+++++ + +
+
+
+
+
+

Property Details

+
+

The “main-context” property

+
  “main-context”             GMainContext *
+

GMainContext to use for the event source.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “session” property

+
  “session”                  SpiceSession *
+

SpiceSession this SpiceAudio is associated with

+

Flags: Read / Write / Construct Only

+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceChannel.html b/doc/reference/html/SpiceChannel.html new file mode 100644 index 0000000..710f3ee --- /dev/null +++ b/doc/reference/html/SpiceChannel.html @@ -0,0 +1,962 @@ + + + + +Spice Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice Channel

+

Spice Channel — the base channel class

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SpiceChannel * + +spice_channel_new () +
+void + +spice_channel_destroy () +
+gboolean + +spice_channel_connect () +
+gboolean + +spice_channel_open_fd () +
+void + +spice_channel_disconnect () +
+gboolean + +spice_channel_test_capability () +
+gboolean + +spice_channel_test_common_capability () +
const gchar * + +spice_channel_type_to_string () +
+gint + +spice_channel_string_to_type () +
+void + +spice_channel_set_capability () +
+void + +spice_channel_flush_async () +
+gboolean + +spice_channel_flush_finish () +
const GError * + +spice_channel_get_error () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
gintchannel-idRead / Write / Construct Only
gintchannel-typeRead / Write / Construct Only
+SpiceSession *spice-sessionRead / Write / Construct Only
gulongtotal-read-bytesRead
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidchannel-eventRun First
voidopen-fdRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
enumSpiceChannelEvent
 SpiceChannel
 SpiceChannelClass
+
+
+

Object Hierarchy

+
    GEnum
+    ╰── SpiceChannelEvent
+    GObject
+    ╰── SpiceChannel
+        ├── SpiceCursorChannel
+        ├── SpiceDisplayChannel
+        ├── SpiceInputsChannel
+        ├── SpiceMainChannel
+        ├── SpicePlaybackChannel
+        ├── SpiceRecordChannel
+        ├── SpiceSmartcardChannel
+        ├── SpiceUsbredirChannel
+        ╰── SpicePortChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpiceChannel is the base class for the different kind of Spice +channel connections, such as SpiceMainChannel, or +SpiceInputsChannel.

+
+
+

Functions

+
+

spice_channel_new ()

+
SpiceChannel *
+spice_channel_new (SpiceSession *s,
+                   int type,
+                   int id);
+

Create a new SpiceChannel of type type +, and channel ID id +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

s

the SpiceSession +the channel is linked to

 

type

the requested SPICECHANNELPRIVATE type

 

id

the channel-id

 
+
+
+

Returns

+

a weak reference to SpiceChannel, the session owns the reference

+
+
+
+
+

spice_channel_destroy ()

+
void
+spice_channel_destroy (SpiceChannel *channel);
+
+

spice_channel_destroy has been deprecated since version 0.27 and should not be used in newly-written code.

+

this function has been deprecated because it is +misleading, the object is not actually destroyed. Instead, it is +recommended to call explicitely spice_channel_disconnect() and +g_object_unref().

+
+

Disconnect and unref the channel +.

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceChannel

 
+
+
+
+
+

spice_channel_connect ()

+
gboolean
+spice_channel_connect (SpiceChannel *channel);
+

Connect the channel, using SpiceSession connection informations

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceChannel

 
+
+
+

Returns

+

TRUE on success.

+
+
+
+
+

spice_channel_open_fd ()

+
gboolean
+spice_channel_open_fd (SpiceChannel *channel,
+                       int fd);
+

Connect the channel using fd + socket.

+

If fd + is -1, a valid fd will be requested later via the +SpiceChannel::open-fd signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceChannel

 

fd

a file descriptor (socket) or -1. +request mechanism

 
+
+
+

Returns

+

TRUE on success.

+
+
+
+
+

spice_channel_disconnect ()

+
void
+spice_channel_disconnect (SpiceChannel *channel,
+                          SpiceChannelEvent reason);
+

Close the socket and reset connection specific data. Finally, emit +reason + “channel-event” on main context if not +SPICE_CHANNEL_NONE.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceChannel

 

reason

a channel event emitted on main context (or SPICE_CHANNEL_NONE)

 
+
+
+
+
+

spice_channel_test_capability ()

+
gboolean
+spice_channel_test_capability (SpiceChannel *channel,
+                               guint32 cap);
+

Test availability of remote "channel kind capability".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceChannel

 

cap

a capability

 
+
+
+

Returns

+

TRUE if cap +(channel kind capability) is available.

+
+
+
+
+

spice_channel_test_common_capability ()

+
gboolean
+spice_channel_test_common_capability (SpiceChannel *channel,
+                                      guint32 cap);
+

Test availability of remote "common channel capability".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceChannel

 

cap

a capability

 
+
+
+

Returns

+

TRUE if cap +(common channel capability) is available.

+
+
+
+
+

spice_channel_type_to_string ()

+
const gchar *
+spice_channel_type_to_string (gint type);
+

Convert a channel-type property value to a string.

+
+

Parameters

+
+++++ + + + + + +

type

a channel-type property value

 
+
+
+

Returns

+

string representation of type +.

+
+

Since: 0.20

+
+
+
+

spice_channel_string_to_type ()

+
gint
+spice_channel_string_to_type (const gchar *str);
+

Convert a channel-type property value to a string.

+
+

Parameters

+
+++++ + + + + + +

str

a string representation of the channel-type property

 
+
+
+

Returns

+

the channel-type property value for a str +channel

+
+

Since: 0.21

+
+
+
+

spice_channel_set_capability ()

+
void
+spice_channel_set_capability (SpiceChannel *channel,
+                              guint32 cap);
+
+

spice_channel_set_capability has been deprecated since version 0.13 and should not be used in newly-written code.

+

this function has been removed

+
+

Enable specific channel-kind capability.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceChannel

 

cap

a capability

 
+
+
+
+
+

spice_channel_flush_async ()

+
void
+spice_channel_flush_async (SpiceChannel *channel,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data);
+

Forces an asynchronous write of all user-space buffered data for +the given channel.

+

When the operation is finished callback will be called. You can +then call spice_channel_flush_finish() to get the result of the +operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceChannel

 

cancellable

optional GCancellable object, NULL to ignore.

[allow-none]

callback

callback to call when the request is satisfied.

[scope async]

user_data

the data to pass to callback function.

[closure]
+
+

Since: 0.15

+
+
+
+

spice_channel_flush_finish ()

+
gboolean
+spice_channel_flush_finish (SpiceChannel *channel,
+                            GAsyncResult *result,
+                            GError **error);
+

Finishes flushing a channel.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceChannel

 

result

a GAsyncResult

 

error

a GError location to store the error occurring, or NULL +to ignore.

 
+
+
+

Returns

+

TRUE if flush operation succeeded, FALSE otherwise.

+
+

Since: 0.15

+
+
+
+

spice_channel_get_error ()

+
const GError *
+spice_channel_get_error (SpiceChannel *channel);
+

Retrieves the GError currently set on channel, if the SpiceChannel +is in error state and can provide additional error details.

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceChannel

 
+
+
+

Returns

+

the pointer to the error, or NULL

+
+

Since: 0.24

+
+
+
+

Types and Values

+
+

enum SpiceChannelEvent

+

An event, emitted by “channel-event” signal.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SPICE_CHANNEL_NONE

+

no event, or ignored event

+
 

SPICE_CHANNEL_OPENED

+

connection is authentified and ready

+
 

SPICE_CHANNEL_SWITCHING

+

disconnecting from the current host and connecting to the target host.

+
 

SPICE_CHANNEL_CLOSED

+

connection is closed normally (sent if channel was ready)

+
 

SPICE_CHANNEL_ERROR_CONNECT

+

connection error

+
 

SPICE_CHANNEL_ERROR_TLS

+

SSL error

+
 

SPICE_CHANNEL_ERROR_LINK

+

error during link process

+
 

SPICE_CHANNEL_ERROR_AUTH

+

authentication error

+
 

SPICE_CHANNEL_ERROR_IO

+

IO error

+
 
+
+
+
+
+

SpiceChannel

+
typedef struct _SpiceChannel SpiceChannel;
+

The SpiceChannel struct is opaque and should not be accessed directly.

+
+
+
+

SpiceChannelClass

+
typedef struct {
+    GObjectClass parent_class;
+
+    /* signals, main context */
+    void (*channel_event)(SpiceChannel *channel, SpiceChannelEvent event);
+    void (*open_fd)(SpiceChannel *channel, int with_tls);
+} SpiceChannelClass;
+
+

Class structure for SpiceChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + +

channel_event ()

Signal class handler for the “channel_event” signal.

 

open_fd ()

Signal class handler for the “open_fd” signal.

 
+
+
+
+
+

Property Details

+
+

The “channel-id” property

+
  “channel-id”               gint
+

Channel ID.

+

Flags: Read / Write / Construct Only

+

Allowed values: >= -1

+

Default value: -1

+
+
+
+

The “channel-type” property

+
  “channel-type”             gint
+

Channel type.

+

Flags: Read / Write / Construct Only

+

Allowed values: >= -1

+

Default value: -1

+
+
+
+

The “spice-session” property

+
  “spice-session”            SpiceSession *
+

Spice session.

+

Flags: Read / Write / Construct Only

+
+
+
+

The “total-read-bytes” property

+
  “total-read-bytes”         gulong
+

Total read bytes.

+

Flags: Read

+
+
+
+

Signal Details

+
+

The “channel-event” signal

+
void
+user_function (SpiceChannel     *channel,
+               SpiceChannelEvent event,
+               gpointer          user_data)
+

The “channel-event” signal is emitted when the +state of the connection is changed. In case of errors, +spice_channel_get_error() may provide additional informations +on the source of the error.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

the channel that emitted the signal

 

event

a SpiceChannelEvent

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “open-fd” signal

+
void
+user_function (SpiceChannel *channel,
+               gint          with_tls,
+               gpointer      user_data)
+

The “open-fd” signal is emitted when a new +connection is requested. This signal is emitted when the +connection is made with spice_session_open_fd().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

the channel that emitted the signal

 

with_tls

wether TLS connection is requested

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceSession, SpiceMainChannel and other channels

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceCursorChannel.html b/doc/reference/html/SpiceCursorChannel.html new file mode 100644 index 0000000..8552532 --- /dev/null +++ b/doc/reference/html/SpiceCursorChannel.html @@ -0,0 +1,359 @@ + + + + +Cursor Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Cursor Channel

+

Cursor Channel — update cursor shape and position

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidcursor-hideRun First
voidcursor-moveRun First
voidcursor-resetRun First
voidcursor-setRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceCursorChannel
structSpiceCursorChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpiceCursorChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The Spice protocol defines a set of messages for controlling cursor +shape and position on the remote display area. The cursor changes +that should be reflected on the display are notified by +signals. See for example “cursor-set” +“cursor-move” signals.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct SpiceCursorChannel

+
struct SpiceCursorChannel;
+

The SpiceCursorChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceCursorChannelClass

+
struct SpiceCursorChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*cursor_set)(SpiceCursorChannel *channel, gint width, gint height,
+                       gint hot_x, gint hot_y, gpointer rgba);
+    void (*cursor_move)(SpiceCursorChannel *channel, gint x, gint y);
+    void (*cursor_hide)(SpiceCursorChannel *channel);
+    void (*cursor_reset)(SpiceCursorChannel *channel);
+};
+
+

Class structure for SpiceCursorChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

cursor_set ()

Signal class handler for the “cursor-set” signal.

 

cursor_move ()

Signal class handler for the “cursor-move” signal.

 

cursor_hide ()

Signal class handler for the “cursor-hide” signal.

 

cursor_reset ()

Signal class handler for the “cursor-reset” signal.

 
+
+
+
+
+

Signal Details

+
+

The “cursor-hide” signal

+
void
+user_function (SpiceCursorChannel *cursor,
+               gpointer            user_data)
+

The “cursor-hide” signal is emitted to hide +the cursor/pointer on the display area.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cursor

the SpiceCursorChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “cursor-move” signal

+
void
+user_function (SpiceCursorChannel *cursor,
+               gint                x,
+               gint                y,
+               gpointer            user_data)
+

The “cursor-move” signal is emitted to update +the cursor position on the display area.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

cursor

the SpiceCursorChannel that emitted the signal

 

x

x position

 

y

y position

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “cursor-reset” signal

+
void
+user_function (SpiceCursorChannel *cursor,
+               gpointer            user_data)
+

The “cursor-reset” signal is emitted to +reset the cursor to its default context.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

cursor

the SpiceCursorChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “cursor-set” signal

+
void
+user_function (SpiceCursorChannel *cursor,
+               gint                width,
+               gint                height,
+               gint                hot_x,
+               gint                hot_y,
+               gpointer            rgba,
+               gpointer            user_data)
+

The “cursor-set” signal is emitted to modify +cursor aspect and position on the display area.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cursor

the SpiceCursorChannel that emitted the signal

 

width

width of the shape

 

height

height of the shape

 

hot_x

horizontal offset of the 'hotspot' of the cursor

 

hot_y

vertical offset of the 'hotspot' of the cursor

 

rgba

32bits shape data, or NULL if default cursor. It might +be freed after the signal is emitted, so make sure to copy it +if you need it later!

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceChannel, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceDisplayChannel.html b/doc/reference/html/SpiceDisplayChannel.html new file mode 100644 index 0000000..b972636 --- /dev/null +++ b/doc/reference/html/SpiceDisplayChannel.html @@ -0,0 +1,914 @@ + + + + +Display Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Display Channel

+

Display Channel — remote display area

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
const SpiceGlScanout * + +spice_display_get_gl_scanout () +
+void + +spice_display_gl_draw_done () +
+gboolean + +spice_display_get_primary () +
+void + +spice_display_change_preferred_compression () +
+void + +spice_gl_scanout_free () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SpiceGlScanout *gl-scanoutRead
guintheightRead
+GArray *monitorsRead
guintmonitors-maxRead
guintwidthRead
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
voiddisplay-invalidateRun First
voiddisplay-markRun First
voiddisplay-primary-createRun First
voiddisplay-primary-destroyRun First
voidgl-draw 
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
structSpiceDisplayChannel
structSpiceDisplayChannelClass
structSpiceDisplayMonitorConfig
structSpiceDisplayPrimary
structSpiceGlScanout
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SpiceGlScanout
+    GObject
+    ╰── SpiceChannel
+        ╰── SpiceDisplayChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

A class that handles the rendering of the remote display and inform +of its updates.

+

The creation of the main graphic buffer is signaled with +“display-primary-create”.

+

The update of regions is notified by +“display-invalidate” signals.

+
+
+

Functions

+
+

spice_display_get_gl_scanout ()

+
const SpiceGlScanout *
+spice_display_get_gl_scanout (SpiceDisplayChannel *channel);
+

Retrieves the GL scanout if available

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceDisplayChannel

 
+
+
+

Returns

+

the current GL scanout, or NULL if none or not valid

+
+

Since: 0.31

+
+
+
+

spice_display_gl_draw_done ()

+
void
+spice_display_gl_draw_done (SpiceDisplayChannel *channel);
+

After a SpiceDisplayChannel::gl-draw is emitted, the client should +draw the current display with the current GL scanout, and must +release the GL resource with a call to spice_display_gl_draw_done() +(failing to do so for each gl-draw may result in a frozen display).

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceDisplayChannel

 
+
+

Since: 0.31

+
+
+
+

spice_display_get_primary ()

+
gboolean
+spice_display_get_primary (SpiceChannel *channel,
+                           guint32 surface_id,
+                           SpiceDisplayPrimary *primary);
+

Retrieve primary display surface surface_id +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceDisplayChannel

 

surface_id

a surface id

 

primary

a SpiceDisplayPrimary

 
+
+
+

Returns

+

TRUE if the primary surface was found and its details +collected in primary +.

+
+
+
+
+

spice_display_change_preferred_compression ()

+
void
+spice_display_change_preferred_compression
+                               (SpiceChannel *channel,
+                                gint compression);
+

Tells the spice server to change the preferred image compression +for the channel +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceDisplayChannel

 

compression

a SpiceImageCompression

 
+
+

Since: 0.31

+
+
+
+

spice_gl_scanout_free ()

+
void
+spice_gl_scanout_free (SpiceGlScanout *scanout);
+
+
+
+

Types and Values

+
+

struct SpiceDisplayChannel

+
struct SpiceDisplayChannel;
+

The SpiceDisplayChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceDisplayChannelClass

+
struct SpiceDisplayChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*display_primary_create)(SpiceChannel *channel, gint format,
+                                   gint width, gint height, gint stride,
+                                   gint shmid, gpointer data);
+    void (*display_primary_destroy)(SpiceChannel *channel);
+    void (*display_invalidate)(SpiceChannel *channel,
+                               gint x, gint y, gint w, gint h);
+    void (*display_mark)(SpiceChannel *channel,
+                         gboolean mark);
+};
+
+

Class structure for SpiceDisplayChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

display_primary_create ()

Signal class handler for the “display-primary-create” signal.

 

display_primary_destroy ()

Signal class handler for the “display-primary-destroy” signal.

 

display_invalidate ()

Signal class handler for the “display-invalidate” signal.

 

display_mark ()

Signal class handler for the “display-mark” signal.

 
+
+
+
+
+

struct SpiceDisplayMonitorConfig

+
struct SpiceDisplayMonitorConfig {
+    guint id;
+    guint surface_id;
+    guint x;
+    guint y;
+    guint width;
+    guint height;
+};
+
+

Holds a monitor configuration.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

guint id;

monitor id

 

guint surface_id;

monitor surface id

 

guint x;

x position of the monitor

 

guint y;

y position of the monitor

 

guint width;

width of the monitor

 

guint height;

height of the monitor

 
+
+
+
+
+

struct SpiceDisplayPrimary

+
struct SpiceDisplayPrimary {
+    enum SpiceSurfaceFmt format;
+    gint width;
+    gint height;
+    gint stride;
+    gint shmid;
+    guint8 *data;
+    gboolean marked;
+};
+
+

Holds the information necessary to use the primary surface.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

enum SpiceSurfaceFmt format;

primary buffer format

 

gint width;

width of the primary

 

gint height;

height of the primary

 

gint stride;

stride of the primary

 

gint shmid;

identifier of the shared memory segment associated with +the data +, or -1 if not shm

 

guint8 *data;

pointer to primary buffer

 

gboolean marked;

whether the display is marked ready

 
+
+
+
+
+

struct SpiceGlScanout

+
struct SpiceGlScanout {
+    gint fd;
+    guint32 width;
+    guint32 height;
+    guint32 stride;
+    guint32 format;
+    gboolean y0top;
+};
+
+

Holds the information necessary for using the GL display scanout.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gint fd;

a drm DMABUF file that can be imported with eglCreateImageKHR

 

guint32 width;

width of the scanout

 

guint32 height;

height of the scanout

 

guint32 stride;

stride of the scanout

 

guint32 format;

the drm fourcc format

 

gboolean y0top;

orientation of the scanout

 
+
+
+
+
+

Property Details

+
+

The “gl-scanout” property

+
  “gl-scanout”               SpiceGlScanout *
+

The last SpiceGlScanout received.

+

Flags: Read

+

Since: 0.31

+
+
+
+

The “height” property

+
  “height”                   guint
+

The primary surface height.

+

Flags: Read

+

Default value: 0

+
+
+
+

The “monitors” property

+
  “monitors”                 GArray *
+

Current monitors configuration.

+

Flags: Read

+

Since: 0.13

+
+
+
+

The “monitors-max” property

+
  “monitors-max”             guint
+

The maximum number of monitors the server or guest supports. +May change during client lifetime, for instance guest may +reboot or dynamically adjust this.

+

Flags: Read

+

Allowed values: [1,256]

+

Default value: 1

+

Since: 0.13

+
+
+
+

The “width” property

+
  “width”                    guint
+

The primary surface width.

+

Flags: Read

+

Default value: 0

+
+
+
+

Signal Details

+
+

The “display-invalidate” signal

+
void
+user_function (SpiceDisplayChannel *display,
+               gint                 x,
+               gint                 y,
+               gint                 width,
+               gint                 height,
+               gpointer             user_data)
+

The “display-invalidate” signal is emitted +when the rectangular region x/y/w/h of the primary buffer is +updated.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

display

the SpiceDisplayChannel that emitted the signal

 

x

x position

 

y

y position

 

width

width

 

height

height

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “display-mark” signal

+
void
+user_function (SpiceDisplayChannel *display,
+               gint                 mark,
+               gpointer             user_data)
+

The “display-mark” signal is emitted when +the RED_DISPLAY_MARK command is received, and the display +should be exposed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

display

the SpiceDisplayChannel that emitted the signal

 

mark

TRUE when the display mark has been received

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “display-primary-create” signal

+
void
+user_function (SpiceDisplayChannel *display,
+               gint                 format,
+               gint                 width,
+               gint                 height,
+               gint                 stride,
+               gint                 shmid,
+               gpointer             imgdata,
+               gpointer             user_data)
+

The “display-primary-create” signal +provides main display buffer data.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

display

the SpiceDisplayChannel that emitted the signal

 

format

SPICE_SURFACE_FMT_32_xRGB or SPICE_SURFACE_FMT_16_555;

 

width

width resolution

 

height

height resolution

 

stride

the buffer stride ("width" padding)

 

shmid

identifier of the shared memory segment associated with +the imgdata +, or -1 if not shm

 

imgdata

pointer to surface buffer

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “display-primary-destroy” signal

+
void
+user_function (SpiceDisplayChannel *display,
+               gpointer             user_data)
+

The “display-primary-destroy” signal is +emitted when the primary surface is freed and should not be +accessed anymore.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

display

the SpiceDisplayChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “gl-draw” signal

+
void
+user_function (SpiceDisplayChannel *display,
+               guint                x,
+               guint                y,
+               guint                width,
+               guint                height,
+               gpointer             user_data)
+

The “draw” signal is emitted when the +rectangular region x/y/w/h of the GL scanout is updated and +must be drawn. When the draw is finished, you must call +spice_display_gl_draw_done() in order to release the GL +resources.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

display

the SpiceDisplayChannel that emitted the signal

 

x

x position

 

y

y position

 

width

width

 

height

height

 

user_data

user data set when the signal handler was connected.

 
+
+

Since: 0.31

+
+
+
+

See Also

+

SpiceChannel, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceFileTransferTask.html b/doc/reference/html/SpiceFileTransferTask.html new file mode 100644 index 0000000..3d9dad7 --- /dev/null +++ b/doc/reference/html/SpiceFileTransferTask.html @@ -0,0 +1,340 @@ + + + + +File Transfer Task: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

File Transfer Task

+

File Transfer Task — Monitoring file transfers

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+double + +spice_file_transfer_task_get_progress () +
+char * + +spice_file_transfer_task_get_filename () +
+void + +spice_file_transfer_task_cancel () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GCancellable *cancellableRead / Write / Construct Only
+SpiceMainChannel *channelRead / Write / Construct Only
+GFile *fileRead / Write / Construct Only
guintidRead / Write / Construct Only
gdoubleprogressRead
+
+
+

Signals

+
+++++ + + + + + +
voidfinishedRun First
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceFileTransferTask
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpiceFileTransferTask is an object that represents a particular file +transfer between the client and the guest. The properties and signals of the +object can be used to monitor the status and result of the transfer. The +Main Channel's “new-file-transfer” signal will be emitted +whenever a new file transfer task is initiated.

+
+
+

Functions

+
+

spice_file_transfer_task_get_progress ()

+
double
+spice_file_transfer_task_get_progress (SpiceFileTransferTask *self);
+

Convenience function for retrieving the current progress of this file +transfer task.

+
+

Parameters

+
+++++ + + + + + +

self

a file transfer task

 
+
+
+

Returns

+

A percentage value between 0 and 100

+
+

Since: 0.31

+
+
+
+

spice_file_transfer_task_get_filename ()

+
char *
+spice_file_transfer_task_get_filename (SpiceFileTransferTask *self);
+

Gets the name of the file being transferred in this task

+
+

Parameters

+
+++++ + + + + + +

self

a file transfer task

 
+
+
+

Returns

+

The basename of the file.

+

[transfer none]

+
+

Since: 0.31

+
+
+
+

spice_file_transfer_task_cancel ()

+
void
+spice_file_transfer_task_cancel (SpiceFileTransferTask *self);
+

Cancels the file transfer task. Note that depending on how the file transfer +was initiated, multiple file transfer tasks may share a single +“cancellable” object, so canceling one task may result +in the cancellation of other tasks.

+
+

Parameters

+
+++++ + + + + + +

self

a file transfer task

 
+
+

Since: 0.31

+
+
+
+

Types and Values

+
+
+

Property Details

+
+

The “cancellable” property

+
  “cancellable”              GCancellable *
+

A cancellable object used to cancel the file transfer

+

Flags: Read / Write / Construct Only

+

Since: 0.31

+
+
+
+

The “channel” property

+
  “channel”                  SpiceMainChannel *
+

The main channel that owns the file transfer task

+

Flags: Read / Write / Construct Only

+

Since: 0.31

+
+
+
+

The “file” property

+
  “file”                     GFile *
+

The file that is being transferred in this file transfer task

+

Flags: Read / Write / Construct Only

+

Since: 0.31

+
+
+
+

The “id” property

+
  “id”                       guint
+

The ID of the file transfer task

+

Flags: Read / Write / Construct Only

+

Default value: 0

+

Since: 0.31

+
+
+
+

The “progress” property

+
  “progress”                 gdouble
+

The current state of the file transfer. This value indicates a +percentage, and ranges from 0 to 100. Listen for change notifications on +this property to be updated whenever the file transfer progress changes.

+

Flags: Read

+

Allowed values: [0,100]

+

Default value: 0

+

Since: 0.31

+
+
+
+

Signal Details

+
+

The “finished” signal

+
void
+user_function (SpiceFileTransferTask *task,
+               GError                *error,
+               gpointer               user_data)
+

The “finished” signal is emitted when the file +transfer has completed transferring to the guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

task

the file transfer task that emitted the signal

 

error

the error state of the transfer. Will be NULL +if the file transfer was successful.

[transfer none]

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+

Since: 0.31

+
+
+
+

See Also

+

SpiceMainChannel

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceInputsChannel.html b/doc/reference/html/SpiceInputsChannel.html new file mode 100644 index 0000000..2e34b62 --- /dev/null +++ b/doc/reference/html/SpiceInputsChannel.html @@ -0,0 +1,614 @@ + + + + +Inputs Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Inputs Channel

+

Inputs Channel — control the server mouse and keyboard

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +spice_inputs_motion () +
+void + +spice_inputs_position () +
+void + +spice_inputs_button_press () +
+void + +spice_inputs_button_release () +
+void + +spice_inputs_key_press () +
+void + +spice_inputs_key_press_and_release () +
+void + +spice_inputs_key_release () +
+void + +spice_inputs_set_key_locks () +
+
+
+

Properties

+
+++++ + + + + + +
gintkey-modifiersRead
+
+
+

Signals

+
+++++ + + + + + +
voidinputs-modifiersRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structSpiceInputsChannel
structSpiceInputsChannelClass
enumSpiceInputsLock
+
+
+

Object Hierarchy

+
    GFlags
+    ╰── SpiceInputsLock
+    GObject
+    ╰── SpiceChannel
+        ╰── SpiceInputsChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

Spice supports sending keyboard key events and keyboard leds +synchronization. The key events are sent using +spice_inputs_key_press() and spice_inputs_key_release() using +a modified variant of PC XT scancodes.

+

Guest keyboard leds state can be manipulated with +spice_inputs_set_key_locks(). When key lock change, a notification +is emitted with “inputs-modifiers” signal.

+
+
+

Functions

+
+

spice_inputs_motion ()

+
void
+spice_inputs_motion (SpiceInputsChannel *channel,
+                     gint dx,
+                     gint dy,
+                     gint button_state);
+

Change mouse position (used in SPICE_MOUSE_MODE_CLIENT).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

dx

delta X mouse coordinates

 

dy

delta Y mouse coordinates

 

button_state

SPICE_MOUSE_BUTTON_MASK flags

 
+
+
+
+
+

spice_inputs_position ()

+
void
+spice_inputs_position (SpiceInputsChannel *channel,
+                       gint x,
+                       gint y,
+                       gint display,
+                       gint button_state);
+

Change mouse position (used in SPICE_MOUSE_MODE_CLIENT).

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

x

X mouse coordinates

 

y

Y mouse coordinates

 

display

display channel id

 

button_state

SPICE_MOUSE_BUTTON_MASK flags

 
+
+
+
+
+

spice_inputs_button_press ()

+
void
+spice_inputs_button_press (SpiceInputsChannel *channel,
+                           gint button,
+                           gint button_state);
+

Press a mouse button.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

button

a SPICE_MOUSE_BUTTON

 

button_state

SPICE_MOUSE_BUTTON_MASK flags

 
+
+
+
+
+

spice_inputs_button_release ()

+
void
+spice_inputs_button_release (SpiceInputsChannel *channel,
+                             gint button,
+                             gint button_state);
+

Release a button.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

button

a SPICE_MOUSE_BUTTON

 

button_state

SPICE_MOUSE_BUTTON_MASK flags

 
+
+
+
+
+

spice_inputs_key_press ()

+
void
+spice_inputs_key_press (SpiceInputsChannel *channel,
+                        guint scancode);
+

Press a key.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

scancode

a PC XT (set 1) key scancode. For scancodes with an 0xe0 +prefix, drop the prefix and OR the scancode with 0x100.

 
+
+
+
+
+

spice_inputs_key_press_and_release ()

+
void
+spice_inputs_key_press_and_release (SpiceInputsChannel *channel,
+                                    guint scancode);
+

Press and release a key event atomically (in the same message).

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

scancode

a PC XT (set 1) key scancode. For scancodes with an 0xe0 +prefix, drop the prefix and OR the scancode with 0x100.

 
+
+

Since: 0.13

+
+
+
+

spice_inputs_key_release ()

+
void
+spice_inputs_key_release (SpiceInputsChannel *channel,
+                          guint scancode);
+

Release a key.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

scancode

a PC XT (set 1) key scancode. For scancodes with an 0xe0 +prefix, drop the prefix and OR the scancode with 0x100.

 
+
+
+
+
+

spice_inputs_set_key_locks ()

+
void
+spice_inputs_set_key_locks (SpiceInputsChannel *channel,
+                            guint locks);
+

Set the keyboard locks on the guest (Caps, Num, Scroll..)

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceInputsChannel

 

locks

SpiceInputsLock modifiers flags

 
+
+
+
+
+

Types and Values

+
+

struct SpiceInputsChannel

+
struct SpiceInputsChannel;
+

The SpiceInputsChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceInputsChannelClass

+
struct SpiceInputsChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*inputs_modifiers)(SpiceChannel *channel);
+};
+
+

Class structure for SpiceInputsChannel.

+
+

Members

+
+++++ + + + + + +

inputs_modifiers ()

Signal class handler for the “inputs-modifiers” signal.

 
+
+
+
+
+

enum SpiceInputsLock

+

Constants used to synchronize modifiers between a client and a guest.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SPICE_INPUTS_SCROLL_LOCK

+

Scroll Lock

+
 

SPICE_INPUTS_NUM_LOCK

+

Num Lock

+
 

SPICE_INPUTS_CAPS_LOCK

+

Caps Lock

+
 
+
+
+
+
+

Property Details

+
+

The “key-modifiers” property

+
  “key-modifiers”            gint
+

Guest keyboard lock/led state.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

Signal Details

+
+

The “inputs-modifiers” signal

+
void
+user_function (SpiceInputsChannel *display,
+               gpointer            user_data)
+

The “inputs-modifiers” signal is emitted when +the guest keyboard locks are changed. You can read the current +state from “key-modifiers” property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

display

the SpiceInputsChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceChannel, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceMainChannel.html b/doc/reference/html/SpiceMainChannel.html new file mode 100644 index 0000000..6efc4b9 --- /dev/null +++ b/doc/reference/html/SpiceMainChannel.html @@ -0,0 +1,1800 @@ + + + + +Main Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Main Channel

+

Main Channel — the main Spice channel

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+void + +spice_main_set_display () +
+void + +spice_main_set_display_enabled () +
+void + +spice_main_update_display () +
+void + +spice_main_update_display_enabled () +
+gboolean + +spice_main_send_monitor_config () +
+gboolean + +spice_main_agent_test_capability () +
+void + +spice_main_request_mouse_mode () +
+void + +spice_main_clipboard_selection_grab () +
+void + +spice_main_clipboard_selection_notify () +
+void + +spice_main_clipboard_selection_release () +
+void + +spice_main_clipboard_selection_request () +
+void + +spice_main_clipboard_grab () +
+void + +spice_main_clipboard_release () +
+void + +spice_main_clipboard_notify () +
+void + +spice_main_clipboard_request () +
+void + +spice_main_file_copy_async () +
+gboolean + +spice_main_file_copy_finish () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gintagent-caps-0Read
gbooleanagent-connectedRead
guintcolor-depthRead / Write / Construct
gbooleandisable-animationRead / Write / Construct
gbooleandisable-display-alignRead / Write / Construct
gbooleandisable-display-positionRead / Write / Construct
gbooleandisable-font-smoothRead / Write / Construct
gbooleandisable-wallpaperRead / Write / Construct
gintmax-clipboardRead / Write / Construct
gintmouse-modeRead
+
+ +
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceMainChannel
structSpiceMainChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpiceMainChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The main channel is the Spice session control channel. It handles +communication initialization (channels list), migrations, mouse +modes, multimedia time, and agent communication.

+
+
+

Functions

+
+

spice_main_set_display ()

+
void
+spice_main_set_display (SpiceMainChannel *channel,
+                        int id,
+                        int x,
+                        int y,
+                        int width,
+                        int height);
+

Notify the guest of screen resolution change. The notification is +sent 1 second later, if no further changes happen.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

id

display ID

 

x

x position

 

y

y position

 

width

display width

 

height

display height

 
+
+
+
+
+

spice_main_set_display_enabled ()

+
void
+spice_main_set_display_enabled (SpiceMainChannel *channel,
+                                int id,
+                                gboolean enabled);
+

When sending monitor configuration to agent guest, don't set +display id +, which the agent translates to disabling the display +id. Note: this will take effect next time the monitor +configuration is sent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

id

display ID (if -1: set all displays)

 

enabled

wether display id +is enabled

 
+
+

Since: 0.6

+
+
+
+

spice_main_update_display ()

+
void
+spice_main_update_display (SpiceMainChannel *channel,
+                           int id,
+                           int x,
+                           int y,
+                           int width,
+                           int height,
+                           gboolean update);
+

Update the display id + resolution.

+

If update + is TRUE, the remote configuration will be updated too +after 1 second without further changes. You can send when you want +without delay the new configuration to the remote with +spice_main_send_monitor_config()

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

id

display ID

 

x

x position

 

y

y position

 

width

display width

 

height

display height

 

update

if TRUE, update guest resolution after 1sec.

 
+
+
+
+
+

spice_main_update_display_enabled ()

+
void
+spice_main_update_display_enabled (SpiceMainChannel *channel,
+                                   int id,
+                                   gboolean enabled,
+                                   gboolean update);
+

When sending monitor configuration to agent guest, if enabled + is FALSE, +don't set display id +, which the agent translates to disabling the display +id. If enabled + is TRUE, the monitor will be included in the next monitor +update. Note: this will take effect next time the monitor configuration is +sent.

+

If update + is FALSE, no server update will be triggered by this call, but +the value will be saved and used in the next configuration update.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

id

display ID (if -1: set all displays)

 

enabled

wether display id +is enabled

 

update

if TRUE, update guest display state after 1sec.

 
+
+

Since: 0.30

+
+
+
+

spice_main_send_monitor_config ()

+
gboolean
+spice_main_send_monitor_config (SpiceMainChannel *channel);
+

Send monitors configuration previously set with +spice_main_set_display() and spice_main_set_display_enabled()

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceMainChannel

 
+
+
+

Returns

+

TRUE on success.

+
+
+
+
+

spice_main_agent_test_capability ()

+
gboolean
+spice_main_agent_test_capability (SpiceMainChannel *channel,
+                                  guint32 cap);
+

Test capability of a remote agent.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

cap

an agent capability identifier

 
+
+
+

Returns

+

TRUE if cap +(channel kind capability) is available.

+
+
+
+
+

spice_main_request_mouse_mode ()

+
void
+spice_main_request_mouse_mode (SpiceMainChannel *channel,
+                               int mode);
+

Request a mouse mode to the server. The server may not be able to +change the mouse mode, but spice-gtk will try to request it +when possible.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

mode

a SPICE_MOUSE_MODE

 
+
+

Since: 0.32

+
+
+
+

spice_main_clipboard_selection_grab ()

+
void
+spice_main_clipboard_selection_grab (SpiceMainChannel *channel,
+                                     guint selection,
+                                     guint32 *types,
+                                     int ntypes);
+

Grab the guest clipboard, with VD_AGENT_CLIPBOARD types +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

selection

one of the clipboard VD_AGENT_CLIPBOARD_SELECTION_*

 

types

an array of VD_AGENT_CLIPBOARD types available in the clipboard

 

ntypes

the number of types +

 
+
+

Since: 0.6

+
+
+
+

spice_main_clipboard_selection_notify ()

+
void
+spice_main_clipboard_selection_notify (SpiceMainChannel *channel,
+                                       guint selection,
+                                       guint32 type,
+                                       const guchar *data,
+                                       size_t size);
+

Send the clipboard data to the guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

selection

one of the clipboard VD_AGENT_CLIPBOARD_SELECTION_*

 

type

a VD_AGENT_CLIPBOARD type

 

data

clipboard data

 

size

data length in bytes

 
+
+

Since: 0.6

+
+
+
+

spice_main_clipboard_selection_release ()

+
void
+spice_main_clipboard_selection_release
+                               (SpiceMainChannel *channel,
+                                guint selection);
+

Release the clipboard (for example, when the client loses the +clipboard grab): Inform the guest no clipboard data is available.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

selection

one of the clipboard VD_AGENT_CLIPBOARD_SELECTION_*

 
+
+

Since: 0.6

+
+
+
+

spice_main_clipboard_selection_request ()

+
void
+spice_main_clipboard_selection_request
+                               (SpiceMainChannel *channel,
+                                guint selection,
+                                guint32 type);
+

Request clipboard data of type + from the guest. The reply is sent +through the “main-clipboard-selection” signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

selection

one of the clipboard VD_AGENT_CLIPBOARD_SELECTION_*

 

type

a VD_AGENT_CLIPBOARD type

 
+
+

Since: 0.6

+
+
+
+

spice_main_clipboard_grab ()

+
void
+spice_main_clipboard_grab (SpiceMainChannel *channel,
+                           guint32 *types,
+                           int ntypes);
+
+

spice_main_clipboard_grab has been deprecated since version 0.6 and should not be used in newly-written code.

+

use spice_main_clipboard_selection_grab() instead.

+
+

Grab the guest clipboard, with VD_AGENT_CLIPBOARD types +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

types

an array of VD_AGENT_CLIPBOARD types available in the clipboard

 

ntypes

the number of types +

 
+
+
+
+
+

spice_main_clipboard_release ()

+
void
+spice_main_clipboard_release (SpiceMainChannel *channel);
+
+

spice_main_clipboard_release has been deprecated since version 0.6 and should not be used in newly-written code.

+

use spice_main_clipboard_selection_release() instead.

+
+

Release the clipboard (for example, when the client loses the +clipboard grab): Inform the guest no clipboard data is available.

+
+

Parameters

+
+++++ + + + + + +

channel

a SpiceMainChannel

 
+
+
+
+
+

spice_main_clipboard_notify ()

+
void
+spice_main_clipboard_notify (SpiceMainChannel *channel,
+                             guint32 type,
+                             const guchar *data,
+                             size_t size);
+
+

spice_main_clipboard_notify has been deprecated since version 0.6 and should not be used in newly-written code.

+

use spice_main_clipboard_selection_notify() instead.

+
+

Send the clipboard data to the guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

type

a VD_AGENT_CLIPBOARD type

 

data

clipboard data

 

size

data length in bytes

 
+
+
+
+
+

spice_main_clipboard_request ()

+
void
+spice_main_clipboard_request (SpiceMainChannel *channel,
+                              guint32 type);
+
+

spice_main_clipboard_request has been deprecated since version 0.6 and should not be used in newly-written code.

+

use spice_main_clipboard_selection_request() instead.

+
+

Request clipboard data of type + from the guest. The reply is sent +through the “main-clipboard” signal.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

type

a VD_AGENT_CLIPBOARD type

 
+
+
+
+
+

spice_main_file_copy_async ()

+
void
+spice_main_file_copy_async (SpiceMainChannel *channel,
+                            GFile **sources,
+                            GFileCopyFlags flags,
+                            GCancellable *cancellable,
+                            GFileProgressCallback progress_callback,
+                            gpointer progress_callback_data,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data);
+

Copies the file sources + to guest

+

If cancellable + is not NULL, then the operation can be cancelled by +triggering the cancellable object from another thread. If the operation +was cancelled, the error G_IO_ERROR_CANCELLED will be returned.

+

If progress_callback + is not NULL, then the operation can be monitored by +setting this to a GFileProgressCallback function. progress_callback_data + +will be passed to this function. It is guaranteed that this callback will +be called after all data has been transferred with the total number of bytes +copied during the operation. Note that before release 0.31, progress_callback +was broken since it only provided status for a single file transfer, but did +not provide a way to determine which file it referred to. In release 0.31, +this behavior was changed so that progress_callback provides the status of +all ongoing file transfers. If you need to monitor the status of individual +files, please connect to the “new-file-transfer” signal.

+

When the operation is finished, callback will be called. You can then call +spice_main_file_copy_finish() to get the result of the operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

sources

a NULL-terminated array of GFile objects to be transferred.

[array zero-terminated=1]

flags

set of GFileCopyFlags

 

cancellable

optional GCancellable object, NULL to ignore.

[allow-none]

progress_callback

function to callback with +progress information, or NULL if progress information is not needed.

[allow-none][scope call]

progress_callback_data

user data to pass to progress_callback +.

[closure]

callback

a GAsyncReadyCallback to call when the request is satisfied

 

user_data

the data to pass to callback function

 
+
+
+
+
+

spice_main_file_copy_finish ()

+
gboolean
+spice_main_file_copy_finish (SpiceMainChannel *channel,
+                             GAsyncResult *result,
+                             GError **error);
+

Finishes copying the file started with +spice_main_file_copy_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

channel

a SpiceMainChannel

 

result

a GAsyncResult.

 

error

a GError, or NULL

 
+
+
+

Returns

+

a TRUE on success, FALSE on error.

+
+
+
+
+

Types and Values

+
+

struct SpiceMainChannel

+
struct SpiceMainChannel;
+

The SpiceMainChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceMainChannelClass

+
struct SpiceMainChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*mouse_update)(SpiceChannel *channel);
+    void (*agent_update)(SpiceChannel *channel);
+};
+
+

Class structure for SpiceMainChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + +

mouse_update ()

Signal class handler for the “mouse-update” signal.

 

agent_update ()

Signal class handler for the “agent-update” signal.

 
+
+
+
+
+

Property Details

+
+

The “agent-caps-0” property

+
  “agent-caps-0”             gint
+

Agent capability bits 0 -> 31.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “agent-connected” property

+
  “agent-connected”          gboolean
+

Whether the agent is connected.

+

Flags: Read

+

Default value: FALSE

+
+
+
+

The “color-depth” property

+
  “color-depth”              guint
+

Color depth.

+

Flags: Read / Write / Construct

+

Allowed values: <= 32

+

Default value: 0

+
+
+
+

The “disable-animation” property

+
  “disable-animation”        gboolean
+

Disable guest animations.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+
+
+
+

The “disable-display-align” property

+
  “disable-display-align”    gboolean
+

Disable automatic horizontal display position alignment.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+

Since: 0.13

+
+
+
+

The “disable-display-position” property

+
  “disable-display-position” gboolean
+

Disable using display position when setting monitor config.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+
+
+
+

The “disable-font-smooth” property

+
  “disable-font-smooth”      gboolean
+

Disable guest font smoothing.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+
+
+
+

The “disable-wallpaper” property

+
  “disable-wallpaper”        gboolean
+

Disable guest wallpaper.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+
+
+
+

The “max-clipboard” property

+
  “max-clipboard”            gint
+

Maximum size of clipboard operations in bytes (default 100MB, +-1 for unlimited size);

+

Flags: Read / Write / Construct

+

Allowed values: >= -1

+

Default value: 104857600

+

Since: 0.22

+
+
+
+

The “mouse-mode” property

+
  “mouse-mode”               gint
+

Spice protocol specifies two mouse modes, client mode and +server mode. In client mode (SPICE_MOUSE_MODE_CLIENT), the +affective mouse is the client side mouse: the client sends +mouse position within the display and the server sends mouse +shape messages. In server mode (SPICE_MOUSE_MODE_SERVER), the +client sends relative mouse movements and the server sends +position and shape commands.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

Signal Details

+
+

The “main-agent-update” signal

+
void
+user_function (SpiceMainChannel *main,
+               gpointer          user_data)
+

Notify when the SpiceMainChannel:agent-connected or +SpiceMainChannel:agent-caps-0 property change.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “main-clipboard” signal

+
void
+user_function (SpiceMainChannel *main,
+               guint             type,
+               gpointer          data,
+               guint             size,
+               gpointer          user_data)
+

Provides guest clipboard data requested by spice_main_clipboard_request().

+
+

SpiceMainChannel::main-clipboard has been deprecated since version 0.6 and should not be used in newly-written code.

+

use SpiceMainChannel::main-clipboard-selection instead.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

type

the VD_AGENT_CLIPBOARD data type

 

data

clipboard data

 

size

size of data +in bytes

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “main-clipboard-grab” signal

+
gboolean
+user_function (SpiceMainChannel *main,
+               gpointer          types,
+               guint             ntypes,
+               gpointer          user_data)
+

Inform when clipboard data is available from the guest, and for +which types +.

+
+

SpiceMainChannel::main-clipboard-grab has been deprecated since version 0.6 and should not be used in newly-written code.

+

use SpiceMainChannel::main-clipboard-selection-grab instead.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

types

the VD_AGENT_CLIPBOARD data types

 

ntypes

the number of types +

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “main-clipboard-release” signal

+
void
+user_function (SpiceMainChannel *main,
+               gpointer          user_data)
+

Inform when the clipboard is released from the guest, when no +clipboard data is available from the guest.

+
+

SpiceMainChannel::main-clipboard-release has been deprecated since version 0.6 and should not be used in newly-written code.

+

use SpiceMainChannel::main-clipboard-selection-release instead.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “main-clipboard-request” signal

+
gboolean
+user_function (SpiceMainChannel *main,
+               guint             types,
+               gpointer          user_data)
+

Request clipboard data from the client.

+
+

SpiceMainChannel::main-clipboard-request has been deprecated since version 0.6 and should not be used in newly-written code.

+

use SpiceMainChannel::main-clipboard-selection-request instead.

+
+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

types

the VD_AGENT_CLIPBOARD request type

 

user_data

user data set when the signal handler was connected.

 
+
+
+

Returns

+

TRUE if the request is successful

+
+

Flags: Run Last

+
+
+
+

The “main-clipboard-selection” signal

+
void
+user_function (SpiceMainChannel *main,
+               guint             selection,
+               guint             type,
+               gpointer          data,
+               guint             size,
+               gpointer          user_data)
+

Informs that clipboard selection data are available.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

selection

a VD_AGENT_CLIPBOARD_SELECTION clipboard

 

type

the VD_AGENT_CLIPBOARD data type

 

data

clipboard data

 

size

size of data +in bytes

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.6

+
+
+
+

The “main-clipboard-selection-grab” signal

+
gboolean
+user_function (SpiceMainChannel *main,
+               guint             selection,
+               gpointer          types,
+               guint             ntypes,
+               gpointer          user_data)
+

Inform when clipboard data is available from the guest, and for +which types +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

selection

a VD_AGENT_CLIPBOARD_SELECTION clipboard

 

types

the VD_AGENT_CLIPBOARD data types

 

ntypes

the number of types +

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.6

+
+
+
+

The “main-clipboard-selection-release” signal

+
void
+user_function (SpiceMainChannel *main,
+               guint             selection,
+               gpointer          user_data)
+

Inform when the clipboard is released from the guest, when no +clipboard data is available from the guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

selection

a VD_AGENT_CLIPBOARD_SELECTION clipboard

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.6

+
+
+
+

The “main-clipboard-selection-request” signal

+
gboolean
+user_function (SpiceMainChannel *main,
+               guint             selection,
+               guint             types,
+               gpointer          user_data)
+

Request clipboard data from the client.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

selection

a VD_AGENT_CLIPBOARD_SELECTION clipboard

 

types

the VD_AGENT_CLIPBOARD request type

 

user_data

user data set when the signal handler was connected.

 
+
+
+

Returns

+

TRUE if the request is successful

+
+

Flags: Run Last

+

Since: 0.6

+
+
+
+

The “main-mouse-update” signal

+
void
+user_function (SpiceMainChannel *main,
+               gpointer          user_data)
+

Notify when the mouse mode has changed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “migration-started” signal

+
void
+user_function (SpiceMainChannel *main,
+               GObject          *session,
+               gpointer          user_data)
+

Inform when migration is starting. Application wishing to make +connections themself can set the “client-sockets” +to TRUE +, then follow “channel-new” creation, and +use spice_channel_open_fd() once the socket is created.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

session

a migration SpiceSession

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+
+
+
+

The “new-file-transfer” signal

+
void
+user_function (SpiceMainChannel *main,
+               GObject          *task,
+               gpointer          user_data)
+

This signal is emitted when a new file transfer task has been initiated +on this channel. Client applications may take a reference on the task + +object and use it to monitor the status of the file transfer task.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

main

the SpiceMainChannel that emitted the signal

 

task

a SpiceFileTransferTask

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.31

+
+
+
+

See Also

+

SpiceChannel, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpicePlaybackChannel.html b/doc/reference/html/SpicePlaybackChannel.html new file mode 100644 index 0000000..5204298 --- /dev/null +++ b/doc/reference/html/SpicePlaybackChannel.html @@ -0,0 +1,456 @@ + + + + +Playback Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Playback Channel

+

Playback Channel — audio stream for playback

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + +
+void + +spice_playback_channel_set_delay () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
guintmin-latencyRead / Write
gbooleanmuteRead / Write
guintnchannelsRead / Write
gpointervolumeRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidplayback-dataRun First
voidplayback-get-delayRun First
voidplayback-startRun First
voidplayback-stopRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpicePlaybackChannel
structSpicePlaybackChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpicePlaybackChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpicePlaybackChannel class handles an audio playback stream. The +audio data is received via “playback-data” +signal, and is controlled by the guest with +“playback-stop” and +“playback-start” signal events.

+

Note: You may be interested to let the SpiceAudio class play and +record audio channels for your application.

+
+
+

Functions

+
+

spice_playback_channel_set_delay ()

+
void
+spice_playback_channel_set_delay (SpicePlaybackChannel *channel,
+                                  guint32 delay_ms);
+

Adjust the multimedia time according to the delay.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

a SpicePlaybackChannel

 

delay_ms

the delay in ms

 
+
+
+
+
+

Types and Values

+
+

struct SpicePlaybackChannel

+
struct SpicePlaybackChannel;
+

The SpicePlaybackChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpicePlaybackChannelClass

+
struct SpicePlaybackChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*playback_start)(SpicePlaybackChannel *channel,
+                           gint format, gint channels, gint freq);
+    void (*playback_data)(SpicePlaybackChannel *channel, gpointer *data, gint size);
+    void (*playback_stop)(SpicePlaybackChannel *channel);
+};
+
+

Class structure for SpicePlaybackChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

playback_start ()

Signal class handler for the “playback-start” signal.

 

playback_data ()

Signal class handler for the “playback-data” signal.

 

playback_stop ()

Signal class handler for the “playback-stop” signal.

 
+
+
+
+
+

Property Details

+
+

The “min-latency” property

+
  “min-latency”              guint
+

Playback min buffer size (ms).

+

Flags: Read / Write

+

Default value: 200

+
+
+
+

The “mute” property

+
  “mute”                     gboolean
+

Mute.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “nchannels” property

+
  “nchannels”                guint
+

Number of Channels.

+

Flags: Read / Write

+

Allowed values: <= 255

+

Default value: 2

+
+
+
+

The “volume” property

+
  “volume”                   gpointer
+

Playback volume.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “playback-data” signal

+
void
+user_function (SpicePlaybackChannel *channel,
+               gpointer              data,
+               gint                  data_size,
+               gpointer              user_data)
+

Provide audio data to be played.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

the SpicePlaybackChannel that emitted the signal

 

data

pointer to audio data

 

data_size

size in byte of data +

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “playback-get-delay” signal

+
void
+user_function (SpicePlaybackChannel *channel,
+               gpointer              user_data)
+

Notify when the current playback delay is requested

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

the SpicePlaybackChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “playback-start” signal

+
void
+user_function (SpicePlaybackChannel *channel,
+               gint                  format,
+               gint                  channels,
+               gint                  rate,
+               gpointer              user_data)
+

Notify when the playback should start, and provide audio format +characteristics.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

the SpicePlaybackChannel that emitted the signal

 

format

a SPICE_AUDIO_FMT

 

channels

number of channels

 

rate

audio rate

 

latency

minimum playback latency in ms

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “playback-stop” signal

+
void
+user_function (SpicePlaybackChannel *channel,
+               gpointer              user_data)
+

Notify when the playback should stop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

the SpicePlaybackChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceChannel, and SpiceAudio

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpicePortChannel.html b/doc/reference/html/SpicePortChannel.html new file mode 100644 index 0000000..8e4aaef --- /dev/null +++ b/doc/reference/html/SpicePortChannel.html @@ -0,0 +1,461 @@ + + + + +Port Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Port Channel

+

Port Channel — private communication channel

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+void + +spice_port_event () +
+void + +spice_port_write_async () +
+gssize + +spice_port_write_finish () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + +
+gchar *port-nameRead
gbooleanport-openedRead
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidport-dataRun Last
voidport-eventRun Last
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpicePortChannel
structSpicePortChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpicePortChannel
+            ╰── SpiceWebdavChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

A Spice port channel carry arbitrary data between the Spice client +and the Spice server. It may be used to provide additional +services on top of a Spice connection. For example, a channel can +be associated with the qemu monitor for the client to interact +with it, just like any qemu chardev. Or it may be used with +various protocols, such as the Spice Controller.

+

A port kind is identified simply by a fqdn, such as +org.qemu.monitor, org.spice.spicy.test or org.ovirt.controller...

+

Once connected and initialized, the client may read the name of the +port via SpicePortChannel:port-name.

+

When the other end of the port is ready, +SpicePortChannel:port-opened is set to TRUE and you can start +receiving data via the signal SpicePortChannel::port-data, or +sending data via spice_port_write_async().

+
+
+

Functions

+
+

spice_port_event ()

+
void
+spice_port_event (SpicePortChannel *port,
+                  guint8 event);
+

Send an event to the port.

+

Note: The values SPICE_PORT_EVENT_CLOSED and +SPICE_PORT_EVENT_OPENED are managed by the channel connection +state.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

port

a SpicePortChannel

 

event

a SPICE_PORT_EVENT value

 
+
+

Since: 0.15

+
+
+
+

spice_port_write_async ()

+
void
+spice_port_write_async (SpicePortChannel *port,
+                        const void *buffer,
+                        gsize count,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data);
+

Request an asynchronous write of count bytes from buffer + into the +port +. When the operation is finished callback + will be called. You +can then call spice_port_write_finish() to get the result of +the operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

port

A SpicePortChannel

 

buffer

the buffer +containing the data to write.

[array length=count][element-type guint8]

count

the number of bytes to write

 

cancellable

optional GCancellable object, NULL to ignore.

[allow-none]

callback

callback to call when the request is satisfied.

[scope async]

user_data

the data to pass to callback function.

[closure]
+
+

Since: 0.15

+
+
+
+

spice_port_write_finish ()

+
gssize
+spice_port_write_finish (SpicePortChannel *port,
+                         GAsyncResult *result,
+                         GError **error);
+

Finishes a port write operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

port

a SpicePortChannel

 

result

a GAsyncResult

 

error

a GError location to store the error occurring, or NULL +to ignore

 
+
+
+

Returns

+

a gssize containing the number of bytes written to the stream.

+
+

Since: 0.15

+
+
+
+

Types and Values

+
+

struct SpicePortChannel

+
struct SpicePortChannel;
+

The SpicePortChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpicePortChannelClass

+
struct SpicePortChannelClass {
+    SpiceChannelClass parent_class;
+};
+
+

Class structure for SpicePortChannel.

+
+

Members

+
+++++ + +
+
+
+
+
+

Property Details

+
+

The “port-name” property

+
  “port-name”                gchar *
+

Port name.

+

Flags: Read

+

Default value: NULL

+
+
+
+

The “port-opened” property

+
  “port-opened”              gboolean
+

Port opened.

+

Flags: Read

+

Default value: FALSE

+
+
+
+

Signal Details

+
+

The “port-data” signal

+
void
+user_function (SpicePortChannel *channel,
+               gpointer          data,
+               gint              size,
+               gpointer          user_data)
+

The “port-data” signal is emitted when new +port data is received.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

the channel that emitted the signal

 

data

the data received

 

size

number of bytes read

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.15

+
+
+
+

The “port-event” signal

+
void
+user_function (SpicePortChannel *channel,
+               gint              event,
+               gpointer          user_data)
+

The “port-event” signal is emitted when new +port event is received.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

the channel that emitted the signal

 

event

the event received

 

size

number of bytes read

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run Last

+

Since: 0.15

+
+
+
+

See Also

+

SpiceChannel

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceRecordChannel.html b/doc/reference/html/SpiceRecordChannel.html new file mode 100644 index 0000000..39cce51 --- /dev/null +++ b/doc/reference/html/SpiceRecordChannel.html @@ -0,0 +1,367 @@ + + + + +Record Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Record Channel

+

Record Channel — audio stream for recording

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + +
+void + +spice_record_send_data () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + +
gbooleanmuteRead / Write
guintnchannelsRead / Write
gpointervolumeRead / Write
+
+
+

Signals

+
+++++ + + + + + + + + + + + + +
voidrecord-startRun First
voidrecord-stopRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceRecordChannel
structSpiceRecordChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpiceRecordChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpiceRecordChannel class handles an audio recording stream. The +audio stream should start when “record-start” is +emitted and should be stopped when “record-stop” +is received.

+

The audio is sent to the guest by calling spice_record_send_data() +with the recorded PCM data.

+

Note: You may be interested to let the SpiceAudio class play and +record audio channels for your application.

+
+
+

Functions

+
+

spice_record_send_data ()

+
void
+spice_record_send_data (SpiceRecordChannel *channel,
+                        gpointer data,
+                        gsize bytes,
+                        guint32 time);
+

Send recorded PCM data to the guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

channel

a SpiceRecordChannel

 

data

PCM data

 

bytes

size of data +

 

time

stream timestamp

 
+
+
+
+
+

Types and Values

+
+

struct SpiceRecordChannel

+
struct SpiceRecordChannel;
+

The SpiceRecordChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceRecordChannelClass

+
struct SpiceRecordChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+    void (*record_start)(SpiceRecordChannel *channel,
+                         gint format, gint channels, gint freq);
+    void (*record_data)(SpiceRecordChannel *channel, gpointer *data, gint size);
+    void (*record_stop)(SpiceRecordChannel *channel);
+};
+
+

Class structure for SpiceRecordChannel.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

record_start ()

Signal class handler for the “record-start” signal.

 

record_data ()

Unused (deprecated).

 

record_stop ()

Signal class handler for the “record-stop” signal.

 
+
+
+
+
+

Property Details

+
+

The “mute” property

+
  “mute”                     gboolean
+

Mute.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “nchannels” property

+
  “nchannels”                guint
+

Number of Channels.

+

Flags: Read / Write

+

Allowed values: <= 255

+

Default value: 2

+
+
+
+

The “volume” property

+
  “volume”                   gpointer
+

Record volume.

+

Flags: Read / Write

+
+
+
+

Signal Details

+
+

The “record-start” signal

+
void
+user_function (SpiceRecordChannel *channel,
+               gint                format,
+               gint                channels,
+               gint                rate,
+               gpointer            user_data)
+

Notify when the recording should start, and provide audio format +characteristics.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

channel

the SpiceRecordChannel that emitted the signal

 

format

a SPICE_AUDIO_FMT

 

channels

number of channels

 

rate

audio rate

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “record-stop” signal

+
void
+user_function (SpiceRecordChannel *channel,
+               gpointer            user_data)
+

Notify when the recording should stop.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

channel

the SpiceRecordChannel that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceChannel, and SpiceAudio

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceSession.html b/doc/reference/html/SpiceSession.html new file mode 100644 index 0000000..4742ac0 --- /dev/null +++ b/doc/reference/html/SpiceSession.html @@ -0,0 +1,1395 @@ + + + + +Spice Session: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice Session

+

Spice Session — handles connection details, and active channels

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SpiceSession * + +spice_session_new () +
+gboolean + +spice_session_connect () +
+gboolean + +spice_session_open_fd () +
+void + +spice_session_disconnect () +
+GList * + +spice_session_get_channels () +
+gboolean + +spice_session_get_read_only () +
+gboolean + +spice_session_has_channel_type () +
+SpiceURI * + +spice_session_get_proxy_uri () +
+gboolean + +spice_session_is_for_migration () +
+GOptionGroup * + +spice_get_option_group () +
+void + +spice_set_session_option () +
+GQuark + +spice_client_error_quark () +
+
+
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+GByteArray *caRead / Write
+gchar *ca-fileRead / Write
gintcache-sizeRead / Write
+gchar *cert-subjectRead / Write
+gchar *ciphersRead / Write
gbooleanclient-socketsRead / Write
gintcolor-depthRead / Write
GStrvdisable-effectsRead / Write
gbooleanenable-audioRead / Write / Construct
gbooleanenable-smartcardRead / Write
gbooleanenable-usbredirRead / Write / Construct
gintglz-window-sizeRead / Write
+gchar *hostRead / Write / Construct
gbooleaninhibit-keyboard-grabRead / Write
SpiceSessionMigrationmigration-stateRead
+gchar *nameRead
+gchar *passwordRead / Write
+gchar *portRead / Write
SpiceImageCompresspreferred-compressionRead / Write
gintprotocolRead / Write / Construct
+gchar *proxyRead / Write
+GByteArray *pubkeyRead / Write
gbooleanread-onlyRead / Write / Construct
GStrvsecure-channelsRead / Write
gbooleanshare-dir-roRead / Write / Construct
+gchar *shared-dirRead / Write / Construct
GStrvsmartcard-certificatesRead / Write
+gchar *smartcard-dbRead / Write
+gchar *tls-portRead / Write
+gchar *unix-pathRead / Write / Construct
+gchar *uriRead / Write
+gchar *usernameRead / Write
gpointeruuidRead
SpiceSessionVerifyverifyRead / Write / Construct
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + +
voidchannel-destroyRun First
voidchannel-newRun First
voidmm-time-resetRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 SpiceSession
 SpiceSessionClass
enumSpiceSessionMigration
enumSpiceSessionVerify
enumSpiceClientError
#defineSPICE_CLIENT_ERROR
+
+
+

Object Hierarchy

+
    GEnum
+    ╰── SpiceSessionMigration
+    GFlags
+    ╰── SpiceSessionVerify
+    GObject
+    ╰── SpiceSession
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The SpiceSession class handles all the SpiceChannel connections. +It's also the class that contains connections informations, such as +“host” and “port”.

+

You can simply set the property “uri” to something like +"spice://127.0.0.1?port=5930" to configure your connection details.

+

You may want to connect to “channel-new” signal, to be +informed of the availability of channels and to interact with +them.

+

For example, when the SpiceInputsChannel is available and get the +event SPICE_CHANNEL_OPENED, you can send key events with +spice_inputs_key_press(). When the SpiceMainChannel is available, +you can start sharing the clipboard... .

+

Once SpiceSession properties set, you can call +spice_session_connect() to start connecting and communicating with +a Spice server.

+
+
+

Functions

+
+

spice_session_new ()

+
SpiceSession *
+spice_session_new (void);
+

Creates a new Spice session.

+
+

Returns

+

a new SpiceSession

+
+
+
+
+

spice_session_connect ()

+
gboolean
+spice_session_connect (SpiceSession *session);
+

Open the session using the “host” and +“port”.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession

 
+
+
+

Returns

+

FALSE if the session state is invalid for connection +request. TRUE if the connection is initiated. To know whether the +connection is established, you must watch for channels creation +(“channel-new”) and the channels state +(“channel-event”).

+
+
+
+
+

spice_session_open_fd ()

+
gboolean
+spice_session_open_fd (SpiceSession *session,
+                       int fd);
+

Open the session using the provided fd + socket file +descriptor. This is useful if you create the fd yourself, for +example to setup a SSH tunnel.

+

Note however that additional sockets will be needed by all the channels +created for session + so users of this API should hook into +SpiceChannel::open-fd signal for each channel they are interested in, and +create and pass a new socket to the channel using spice_channel_open_fd, in +the signal callback.

+

If fd + is -1, a valid fd will be requested later via the +SpiceChannel::open-fd signal. Typically, you would want to just pass -1 as +fd + this call since you will have to hook to SpiceChannel::open-fd signal +anyway.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SpiceSession

 

fd

a file descriptor (socket) or -1

 
+
+
+

Returns

+

TRUE on success.

+
+
+
+
+

spice_session_disconnect ()

+
void
+spice_session_disconnect (SpiceSession *session);
+

Disconnect the session +, and destroy all channels.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession

 
+
+
+
+
+

spice_session_get_channels ()

+
GList *
+spice_session_get_channels (SpiceSession *session);
+

Get the list of current channels associated with this session +.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession

 
+
+
+

Returns

+

a GList +of unowned SpiceChannel channels.

+

[element-type SpiceChannel][transfer container]

+
+
+
+
+

spice_session_get_read_only ()

+
gboolean
+spice_session_get_read_only (SpiceSession *session);
+

Checks whether the session + is read-only.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession

 
+
+
+

Returns

+

whether the session +is in read-only mode.

+
+
+
+
+

spice_session_has_channel_type ()

+
gboolean
+spice_session_has_channel_type (SpiceSession *session,
+                                gint type);
+

See if there is a type + channel in the channels associated with this +session +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SpiceSession

 

type

a “channel-type”

 
+
+
+

Returns

+

TRUE if a type +channel is available otherwise FALSE.

+
+
+
+
+

spice_session_get_proxy_uri ()

+
SpiceURI *
+spice_session_get_proxy_uri (SpiceSession *session);
+

Gets the session + proxy uri.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession

 
+
+
+

Returns

+

the session proxy SpiceURI or NULL.

+

[transfer none]

+
+

Since: 0.24

+
+
+
+

spice_session_is_for_migration ()

+
gboolean
+spice_session_is_for_migration (SpiceSession *session);
+

During seamless migration, channels may be created to establish a +connection with the target, but they are temporary and should only +handle migration steps. In order to avoid other interactions with +the client, channels should check this value.

+
+

Parameters

+
+++++ + + + + + +

session

a Spice session

 
+
+
+

Returns

+

TRUE if the session is a copy created during migration

+
+

Since: 0.27

+
+
+
+

spice_get_option_group ()

+
GOptionGroup *
+spice_get_option_group (void);
+

Gets commandline options.

+

Bindings for other languages are available since 0.32

+
+

Returns

+

a GOptionGroup for the commandline +arguments specific to Spice. You have to call +spice_set_session_option() after to set the options on a +SpiceSession.

+

[transfer full]

+
+
+
+
+

spice_set_session_option ()

+
void
+spice_set_session_option (SpiceSession *session);
+

Set various properties on session +, according to the commandline +arguments given to spice_get_option_group() option group.

+
+

Parameters

+
+++++ + + + + + +

session

a SpiceSession to set option upon

 
+
+
+
+
+

spice_client_error_quark ()

+
GQuark
+spice_client_error_quark (void);
+

Gets a GQuark representing the string "spice-client-error-quark"

+
+

Returns

+

the GQuark representing the string.

+
+
+
+
+

Types and Values

+
+

SpiceSession

+
typedef struct _SpiceSession SpiceSession;
+

The SpiceSession struct is opaque and should not be accessed directly.

+
+
+
+

SpiceSessionClass

+
typedef struct {
+    GObjectClass parent_class;
+
+    /* signals */
+    void (*channel_new)(SpiceSession *session, SpiceChannel *channel);
+    void (*channel_destroy)(SpiceSession *session, SpiceChannel *channel);
+} SpiceSessionClass;
+
+

Class structure for SpiceSession.

+
+

Members

+
+++++ + + + + + + + + + + + + +

channel_new ()

Signal class handler for the “channel_new” signal.

 

channel_destroy ()

Signal class handler for the “channel_destroy” signal.

 
+
+
+
+
+

enum SpiceSessionMigration

+

Session migration state.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

SPICE_SESSION_MIGRATION_NONE

+

no migration going on

+
 

SPICE_SESSION_MIGRATION_SWITCHING

+

the session is switching host (destroy and reconnect)

+
 

SPICE_SESSION_MIGRATION_MIGRATING

+

the session is migrating seamlessly (reconnect)

+
 

SPICE_SESSION_MIGRATION_CONNECTING

+

the migration is connecting to destination (Since: 0.27)

+
 
+
+
+
+
+

enum SpiceSessionVerify

+

Peer certificate verification parameters flags.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SPICE_SESSION_VERIFY_PUBKEY

+

verify certificate public key matching

+
 

SPICE_SESSION_VERIFY_HOSTNAME

+

verify certificate hostname matching

+
 

SPICE_SESSION_VERIFY_SUBJECT

+

verify certificate subject matching

+
 
+
+
+
+
+

enum SpiceClientError

+

Error codes returned by spice-client API.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

SPICE_CLIENT_ERROR_FAILED

+

generic error code

+
 

SPICE_CLIENT_ERROR_USB_DEVICE_REJECTED

+

device redirection rejected by host

+
 

SPICE_CLIENT_ERROR_USB_DEVICE_LOST

+

device disconnected (fatal IO error)

+
 

SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD

+

password is required

+
 

SPICE_CLIENT_ERROR_AUTH_NEEDS_USERNAME

+

username is required

+
 

SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME

+

password and username are required

+
 

SPICE_CLIENT_ERROR_USB_SERVICE

+

USB service error

+
 
+
+
+
+
+

SPICE_CLIENT_ERROR

+
#define SPICE_CLIENT_ERROR spice_client_error_quark()
+
+

Error domain for spice client errors.

+
+
+
+

Property Details

+
+

The “ca” property

+
  “ca”                       GByteArray *
+

CA certificates in PEM format. The text data can contain +several CA certificates identified by:

+

-----BEGIN CERTIFICATE----- + ... (CA certificate in base64 encoding) ... + -----END CERTIFICATE-----

+

Flags: Read / Write

+

Since: 0.15

+
+
+
+

The “ca-file” property

+
  “ca-file”                  gchar *
+

File holding the CA certificates for the host the client is +connecting to

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “cache-size” property

+
  “cache-size”               gint
+

Images cache size. If 0, don't set.

+

Flags: Read / Write

+

Allowed values: >= 0

+

Default value: 0

+

Since: 0.9

+
+
+
+

The “cert-subject” property

+
  “cert-subject”             gchar *
+

Certificate subject to check.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “ciphers” property

+
  “ciphers”                  gchar *
+

SSL cipher list.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “client-sockets” property

+
  “client-sockets”           gboolean
+

Sockets are provided by the client.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “color-depth” property

+
  “color-depth”              gint
+

Display color depth to set on new display channels. If 0, don't set.

+

Flags: Read / Write

+

Allowed values: [0,32]

+

Default value: 0

+

Since: 0.7

+
+
+
+

The “disable-effects” property

+
  “disable-effects”          GStrv
+

A string array of effects to disable. The settings will +be applied on new display channels. The following effets can be +disabled "wallpaper", "font-smooth", "animation", and "all", +which will disable all the effects. If NULL, don't apply changes.

+

Flags: Read / Write

+

Since: 0.7

+
+
+
+

The “enable-audio” property

+
  “enable-audio”             gboolean
+

If set to TRUE, the audio channels will be enabled for +playback and recording.

+

Flags: Read / Write / Construct

+

Default value: TRUE

+

Since: 0.8

+
+
+
+

The “enable-smartcard” property

+
  “enable-smartcard”         gboolean
+

If set to TRUE, the smartcard channel will be enabled and smartcard +events will be forwarded to the guest

+

Flags: Read / Write

+

Default value: FALSE

+

Since: 0.7

+
+
+
+

The “enable-usbredir” property

+
  “enable-usbredir”          gboolean
+

If set to TRUE, the usbredir channel will be enabled and USB devices +can be redirected to the guest

+

Flags: Read / Write / Construct

+

Default value: TRUE

+

Since: 0.8

+
+
+
+

The “glz-window-size” property

+
  “glz-window-size”          gint
+

Glz window size. If 0, don't set.

+

Flags: Read / Write

+

Allowed values: [0,134217728]

+

Default value: 0

+

Since: 0.9

+
+
+
+

The “host” property

+
  “host”                     gchar *
+

URL of the SPICE host to connect to

+

Flags: Read / Write / Construct

+

Default value: "localhost"

+
+
+
+

The “inhibit-keyboard-grab” property

+
  “inhibit-keyboard-grab”    gboolean
+

Request that SpiceDisplays don't grab the keyboard.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “migration-state” property

+
  “migration-state”          SpiceSessionMigration
+

SpiceSessionMigration bit field indicating if a migration is in +progress

+

Flags: Read

+

Default value: SPICE_SESSION_MIGRATION_NONE

+
+
+
+

The “name” property

+
  “name”                     gchar *
+

Spice server name.

+

Flags: Read

+

Default value: NULL

+

Since: 0.11

+
+
+
+

The “password” property

+
  “password”                 gchar *
+

TLS password to use

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “port” property

+
  “port”                     gchar *
+

Port to connect to for unencrypted sessions

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “preferred-compression” property

+
  “preferred-compression”    SpiceImageCompress
+

The image compression algorithm the client prefers to use. It is +reported to the server.

+

Flags: Read / Write

+

Default value: SPICE_IMAGE_COMPRESSION_INVALID

+

Since: 0.29

+
+
+
+

The “protocol” property

+
  “protocol”                 gint
+

Version of the SPICE protocol to use

+

Flags: Read / Write / Construct

+

Allowed values: [1,2]

+

Default value: 2

+
+
+
+

The “proxy” property

+
  “proxy”                    gchar *
+

URI to the proxy server to use when doing network connection. +of the form [protocol://]<host>[:port]

+

Flags: Read / Write

+

Default value: NULL

+

Since: 0.17

+
+
+
+

The “pubkey” property

+
  “pubkey”                   GByteArray *
+

Public key to check.

+

Flags: Read / Write

+
+
+
+

The “read-only” property

+
  “read-only”                gboolean
+

Whether this connection is read-only mode.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+

Since: 0.8

+
+
+
+

The “secure-channels” property

+
  “secure-channels”          GStrv
+

A string array of channel types to be secured.

+

Flags: Read / Write

+

Since: 0.20

+
+
+
+

The “share-dir-ro” property

+
  “share-dir-ro”             gboolean
+

Whether to share the directory read-only.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+

Since: 0.28

+
+
+
+

The “shared-dir” property

+
  “shared-dir”               gchar *
+

Location of the shared directory

+

Flags: Read / Write / Construct

+

Default value: "/home/elmarco/Public"

+

Since: 0.24

+
+
+
+

The “smartcard-certificates” property

+
  “smartcard-certificates”   GStrv
+

This property is used when one wants to simulate a smartcard with no +hardware smartcard reader. If it's set to a NULL-terminated string +array containing the names of 3 valid certificates, these will be +used to simulate a smartcard in the guest +See also spice_smartcard_manager_insert_card()

+

Flags: Read / Write

+

Since: 0.7

+
+
+
+

The “smartcard-db” property

+
  “smartcard-db”             gchar *
+

Path to the NSS certificate database containing the certificates to +use to simulate a software smartcard

+

Flags: Read / Write

+

Default value: NULL

+

Since: 0.7

+
+
+
+

The “tls-port” property

+
  “tls-port”                 gchar *
+

Port to connect to for TLS sessions

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “unix-path” property

+
  “unix-path”                gchar *
+

Path of the Unix socket to connect to

+

Flags: Read / Write / Construct

+

Default value: NULL

+

Since: 0.28

+
+
+
+

The “uri” property

+
  “uri”                      gchar *
+

URI of the SPICE host to connect to. The URI is of the form +spice://hostname?port=XXX or spice://hostname?tls_port=XXX

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “username” property

+
  “username”                 gchar *
+

Username to use

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “uuid” property

+
  “uuid”                     gpointer
+

Spice server uuid.

+

Flags: Read

+

Since: 0.11

+
+
+
+

The “verify” property

+
  “verify”                   SpiceSessionVerify
+

SpiceSessionVerify bit field indicating which parts of the peer +certificate should be checked

+

Flags: Read / Write / Construct

+

Default value: SPICE_SESSION_VERIFY_HOSTNAME

+
+
+
+

Signal Details

+
+

The “channel-destroy” signal

+
void
+user_function (SpiceSession *session,
+               SpiceChannel *channel,
+               gpointer      user_data)
+

The “channel-destroy” signal is emitted each time a SpiceChannel is destroyed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the session that emitted the signal

 

channel

the destroyed SpiceChannel

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “channel-new” signal

+
void
+user_function (SpiceSession *session,
+               SpiceChannel *channel,
+               gpointer      user_data)
+

The “channel-new” signal is emitted each time a SpiceChannel is created.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

the session that emitted the signal

 

channel

the new SpiceChannel

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “mm-time-reset” signal

+
void
+user_function (SpiceSession *session,
+               gpointer      user_data)
+

The “mm-time-reset” is emitted when we identify discontinuity in mm-time

+

Since 0.20

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

the session that emitted the signal

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

See Also

+

SpiceChannel, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceSmartcardChannel.html b/doc/reference/html/SpiceSmartcardChannel.html new file mode 100644 index 0000000..de2f3bf --- /dev/null +++ b/doc/reference/html/SpiceSmartcardChannel.html @@ -0,0 +1,130 @@ + + + + +Smartcard Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Smartcard Channel

+

Smartcard Channel — smartcard authentication

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceSmartcardChannel
structSpiceSmartcardChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpiceSmartcardChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The Spice protocol defines a set of messages to forward smartcard +information from the Spice client to the VM. This channel handles +these messages. While it's mainly focus on smartcard readers and +smartcards, it's also possible to use it with a software smartcard +(ie a set of 3 certificates from the client machine). +This class doesn't provide useful methods, see SpiceSession properties +for a way to enable/disable this channel, and SpiceSmartcardManager +if you want to detect smartcard reader hotplug/unplug, and smartcard +insertion/removal.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct SpiceSmartcardChannel

+
struct SpiceSmartcardChannel;
+

The SpiceSmartcardChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceSmartcardChannelClass

+
struct SpiceSmartcardChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+};
+
+

Class structure for SpiceSmartcardChannel.

+
+

Members

+
+++++ + +
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceSmartcardManager.html b/doc/reference/html/SpiceSmartcardManager.html new file mode 100644 index 0000000..bd3cba3 --- /dev/null +++ b/doc/reference/html/SpiceSmartcardManager.html @@ -0,0 +1,607 @@ + + + + +Spice Smartcard Manager: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice Smartcard Manager

+

Spice Smartcard Manager — smartcard management

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+ +
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidcard-insertedRun First
voidcard-removedRun First
voidreader-addedRun First
voidreader-removedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structSpiceSmartcardManager
structSpiceSmartcardManagerClass
 SpiceSmartcardReader
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceSmartcardManager
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpiceSmartcardManager monitors smartcard reader plugging/unplugging, +and smartcard insertions/removals. It also provides methods to handle +software smartcards (to emulate a smartcard reader/smartcard on the +guest using 3 certificates available to the client).

+
+
+

Functions

+
+

spice_smartcard_manager_get ()

+
SpiceSmartcardManager *
+spice_smartcard_manager_get (void);
+

SpiceSmartcardManager is a singleton, use this function to get a pointer +to it. A new SpiceSmartcardManager instance will be created the first +time this function is called

+
+

Returns

+

a weak reference to the SpiceSmartcardManager.

+

[transfer none]

+
+
+
+
+

spice_smartcard_manager_get_readers ()

+
GList *
+spice_smartcard_manager_get_readers (SpiceSmartcardManager *manager);
+

Gets the list of smartcard readers that are currently available, they +can be either software (emulated) readers, or hardware ones.

+
+

Parameters

+
+++++ + + + + + +

manager

a SpiceSmartcardManager

 
+
+
+

Returns

+

a newly +allocated list of SpiceSmartcardReader instances, or NULL if none were +found. When no longer needed, the list must be freed after unreferencing +its elements with g_boxed_free().

+

[element-type SpiceSmartcardReader][transfer full]

+
+

Since: 0.20

+
+
+
+

spice_smartcard_manager_insert_card ()

+
gboolean
+spice_smartcard_manager_insert_card (SpiceSmartcardManager *manager);
+

Simulates the insertion of a smartcard in the guest. Valid certificates +must have been set in “smartcard-certificates” for software +smartcard support to work. At the moment, only one software smartcard +reader is supported, that's why there is no parameter to indicate which +reader to insert the card in.

+
+

Parameters

+
+++++ + + + + + +

manager

a SpiceSmartcardManager

 
+
+
+

Returns

+

TRUE if smartcard insertion was successfully simulated, FALSE +if this failed, or if software smartcard support isn't enabled.

+
+

Since: 0.20

+
+
+
+

spice_smartcard_manager_remove_card ()

+
gboolean
+spice_smartcard_manager_remove_card (SpiceSmartcardManager *manager);
+

Simulates the removal of a smartcard in the guest. At the moment, only +one software smartcard reader is supported, that's why there is no +parameter to indicate which reader to insert the card in.

+
+

Parameters

+
+++++ + + + + + +

manager

a SpiceSmartcardManager

 
+
+
+

Returns

+

TRUE if smartcard removal was successfully simulated, FALSE +if this failed, or if software smartcard support isn't enabled.

+
+

Since: 0.20

+
+
+
+

spice_smartcard_reader_is_software ()

+
gboolean
+spice_smartcard_reader_is_software (SpiceSmartcardReader *reader);
+

Tests if reader + is a software (emulated) smartcard reader.

+
+

Parameters

+
+++++ + + + + + +

reader

a SpiceSmartcardReader

 
+
+
+

Returns

+

TRUE if reader +is a software (emulated) smartcard reader, +FALSE otherwise

+
+
+
+
+

spice_smartcard_reader_insert_card ()

+
gboolean
+spice_smartcard_reader_insert_card (SpiceSmartcardReader *reader);
+

Simulates insertion of a smartcard in the software smartcard reader +reader +. If reader + is not a software smartcard reader, FALSE will be +returned.

+
+

Parameters

+
+++++ + + + + + +

reader

a SpiceSmartcardReader

 
+
+
+

Returns

+

TRUE if insertion of a card was successfully simulated, FALSE +otherwise

+
+
+
+
+

spice_smartcard_reader_remove_card ()

+
gboolean
+spice_smartcard_reader_remove_card (SpiceSmartcardReader *reader);
+

Simulates removal of a smartcard from the software smartcard reader +reader +. If reader + is not a software smartcard reader, FALSE will be +returned.

+
+

Parameters

+
+++++ + + + + + +

reader

a SpiceSmartcardReader

 
+
+
+

Returns

+

TRUE if removal of a card was successfully simulated, FALSE +otherwise

+
+
+
+
+

Types and Values

+
+

struct SpiceSmartcardManager

+
struct SpiceSmartcardManager;
+

The SpiceSmartcardManager struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceSmartcardManagerClass

+
struct SpiceSmartcardManagerClass {
+    GObjectClass parent_class;
+    /* signals */
+    void (*reader_added)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader);
+    void (*reader_removed)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader);
+    void (*card_inserted)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader);
+    void (*card_removed)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader );
+};
+
+

Class structure for SpiceSmartcardManager.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

reader_added ()

Signal class handler for the “reader_added” signal.

 

reader_removed ()

Signal class handler for the “reader_removed” signal.

 

card_inserted ()

Signal class handler for the “card_inserted” signal.

 

card_removed ()

Signal class handler for the “card_removed” signal.

 
+
+
+
+
+

SpiceSmartcardReader

+
typedef struct _SpiceSmartcardReader SpiceSmartcardReader;
+

The SpiceSmartcardReader struct is opaque and cannot be accessed directly.

+
+
+
+

Signal Details

+
+

The “card-inserted” signal

+
void
+user_function (SpiceSmartcardManager *manager,
+               VReader               *vreader,
+               gpointer               user_data)
+

The “card-inserted” signal is emitted whenever +a smartcard is inserted in a reader

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceSmartcardManager that emitted the signal

 

vreader

VReader boxed object corresponding to the reader a new +card was inserted in

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “card-removed” signal

+
void
+user_function (SpiceSmartcardManager *manager,
+               VReader               *vreader,
+               gpointer               user_data)
+

The “card-removed” signal is emitted whenever +a smartcard was removed from a reader.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceSmartcardManager that emitted the signal

 

vreader

VReader boxed object corresponding to the reader a card +was removed from

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “reader-added” signal

+
void
+user_function (SpiceSmartcardManager *manager,
+               VReader               *vreader,
+               gpointer               user_data)
+

The “reader-added” signal is emitted whenever +a new smartcard reader (software or hardware) has been plugged in.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceSmartcardManager that emitted the signal

 

vreader

VReader boxed object corresponding to the added reader

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “reader-removed” signal

+
void
+user_function (SpiceSmartcardManager *manager,
+               VReader               *vreader,
+               gpointer               user_data)
+

The “reader-removed” signal is emitted whenever +a smartcard reader (software or hardware) has been removed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceSmartcardManager that emitted the signal

 

vreader

VReader boxed object corresponding to the removed reader

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceUsbDeviceManager.html b/doc/reference/html/SpiceUsbDeviceManager.html new file mode 100644 index 0000000..003a2ba --- /dev/null +++ b/doc/reference/html/SpiceUsbDeviceManager.html @@ -0,0 +1,1070 @@ + + + + +Spice USB Manager: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice USB Manager

+

Spice USB Manager — USB device management

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+ +
+

Properties

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
gbooleanauto-connectRead / Write
+gchar *auto-connect-filterRead / Write / Construct
gintfree-channelsRead
+gchar *redirect-on-connectRead / Write
+SpiceSession *sessionRead / Write / Construct Only
+
+
+

Signals

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
voidauto-connect-failedRun First
voiddevice-addedRun First
voiddevice-errorRun First
voiddevice-removedRun First
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
structSpiceUsbDeviceManager
structSpiceUsbDeviceManagerClass
 SpiceUsbDevice
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SpiceUsbDevice
+    GObject
+    ╰── SpiceUsbDeviceManager
+
+
+
+

Implemented Interfaces

+

+SpiceUsbDeviceManager implements + GInitable.

+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

SpiceUsbDeviceManager monitors USB redirection channels and USB +devices plugging/unplugging. If “auto-connect” +is set to TRUE, it will automatically connect newly plugged USB +devices to available channels.

+

There should always be a 1:1 relation between SpiceUsbDeviceManager objects +and SpiceSession objects. Therefor there is no +spice_usb_device_manager_new, instead there is +spice_usb_device_manager_get() which ensures this 1:1 relation.

+
+
+

Functions

+
+

spice_usb_device_manager_get ()

+
SpiceUsbDeviceManager *
+spice_usb_device_manager_get (SpiceSession *session,
+                              GError **err);
+

Gets the SpiceUsbDeviceManager associated with the passed in SpiceSession. +A new SpiceUsbDeviceManager instance will be created the first time this +function is called for a certain SpiceSession.

+

Note that this function returns a weak reference, which should not be used +after the SpiceSession itself has been unref-ed by the caller.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

SpiceSession for which to get the SpiceUsbDeviceManager

 

err

a return location for GError, or NULL.

[allow-none]
+
+
+

Returns

+

a weak reference to the SpiceUsbDeviceManager associated with the passed in SpiceSession.

+

[transfer none]

+
+
+
+
+

spice_usb_device_manager_get_devices ()

+
GPtrArray *
+spice_usb_device_manager_get_devices (SpiceUsbDeviceManager *manager);
+

Finds devices associated with the manager +

+
+

Parameters

+
+++++ + + + + + +

manager

the SpiceUsbDeviceManager manager

 
+
+
+

Returns

+

a GPtrArray array of SpiceUsbDevice.

+

[element-type SpiceUsbDevice][transfer full]

+
+
+
+
+

spice_usb_device_manager_get_devices_with_filter ()

+
GPtrArray *
+spice_usb_device_manager_get_devices_with_filter
+                               (SpiceUsbDeviceManager *manager,
+                                const gchar *filter);
+

Finds devices associated with the manager + complying with the filter +

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager manager

 

filter

filter string for selecting which devices to return, +see “auto-connect-filter” for the filter +string format.

[allow-none]
+
+
+

Returns

+

a +GPtrArray array of SpiceUsbDevice.

+

[element-type SpiceUsbDevice][transfer full]

+
+

Since: 0.20

+
+
+
+

spice_usb_device_manager_is_device_connected ()

+
gboolean
+spice_usb_device_manager_is_device_connected
+                               (SpiceUsbDeviceManager *manager,
+                                SpiceUsbDevice *device);
+

Finds if the device + is connected.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager manager

 

device

a SpiceUsbDevice

 
+
+
+

Returns

+

TRUE if device +has an associated USB redirection channel

+
+
+
+
+

spice_usb_device_manager_is_redirecting ()

+
gboolean
+spice_usb_device_manager_is_redirecting
+                               (SpiceUsbDeviceManager *self);
+

Checks whether a device is being redirected

+
+

Parameters

+
+++++ + + + + + +

self

the SpiceUsbDeviceManager manager

 
+
+
+

Returns

+

TRUE if device redirection negotiation flow is in progress

+
+

Since: 0.32

+
+
+
+

spice_usb_device_manager_can_redirect_device ()

+
gboolean
+spice_usb_device_manager_can_redirect_device
+                               (SpiceUsbDeviceManager *self,
+                                SpiceUsbDevice *device,
+                                GError **err);
+

Checks whether it is possible to redirect the device +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

the SpiceUsbDeviceManager manager

 

device

a SpiceUsbDevice to disconnect

 

err

a return location for a GError, or NULL.

[allow-none]
+
+
+

Returns

+

TRUE if device +can be redirected

+
+
+
+
+

spice_usb_device_manager_connect_device_async ()

+
void
+spice_usb_device_manager_connect_device_async
+                               (SpiceUsbDeviceManager *self,
+                                SpiceUsbDevice *device,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data);
+

Asynchronously connects the device +. When completed, callback + will be called. +Then it is possible to call spice_usb_device_manager_connect_device_finish() +to get the result of the operation.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

self

a SpiceUsbDeviceManager.

 

device

a SpiceUsbDevice to redirect

 

cancellable

optional GCancellable object, NULL to ignore.

[allow-none]

callback

a GAsyncReadyCallback to call when the request is satisfied

 

user_data

the data to pass to callback function

 
+
+
+
+
+

spice_usb_device_manager_connect_device_finish ()

+
gboolean
+spice_usb_device_manager_connect_device_finish
+                               (SpiceUsbDeviceManager *self,
+                                GAsyncResult *res,
+                                GError **err);
+

Finishes an async operation. See spice_usb_device_manager_connect_device_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

a SpiceUsbDeviceManager.

 

res

a GAsyncResult

 

err

a return location for a GError, or NULL.

[allow-none]
+
+
+

Returns

+

TRUE if connection is successful

+
+
+
+
+

spice_usb_device_manager_disconnect_device ()

+
void
+spice_usb_device_manager_disconnect_device
+                               (SpiceUsbDeviceManager *manager,
+                                SpiceUsbDevice *device);
+

spice_usb_device_manager_disconnect_device is deprecated and should not be used in newly-written code.

+

Disconnects the device +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager manager

 

device

a SpiceUsbDevice to disconnect

 
+
+
+
+
+

spice_usb_device_manager_disconnect_device_async ()

+
void
+spice_usb_device_manager_disconnect_device_async
+                               (SpiceUsbDeviceManager *manager,
+                                SpiceUsbDevice *device,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data);
+
+
+
+

spice_usb_device_manager_disconnect_device_finish ()

+
gboolean
+spice_usb_device_manager_disconnect_device_finish
+                               (SpiceUsbDeviceManager *self,
+                                GAsyncResult *res,
+                                GError **err);
+

Finishes an async operation. See spice_usb_device_manager_disconnect_device_async().

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

self

a SpiceUsbDeviceManager.

 

res

a GAsyncResult

 

err

a return location for a GError, or NULL.

[allow-none]
+
+
+

Returns

+

TRUE if disconnection is successful

+
+
+
+
+

spice_usb_device_get_description ()

+
gchar *
+spice_usb_device_get_description (SpiceUsbDevice *device,
+                                  const gchar *format);
+

Get a string describing the device which is suitable as a description of +the device for the end user. The returned string should be freed with +g_free() when no longer needed.

+

The format + positional parameters are the following:

+
    +
  • '%1$s' manufacturer

  • +
  • '%2$s' product

  • +
  • '%3$s' descriptor (a [vendor_id:product_id] string)

  • +
  • '%4$d' bus

  • +
  • '%5$d' address

  • +
+

(the default format string is "%s %s %s at %d-%d")

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

device

SpiceUsbDevice to get the description of

 

format

an optional printf() format string with +positional parameters.

[allow-none]
+
+
+

Returns

+

a newly-allocated string holding the description, or NULL if failed

+
+
+
+
+

spice_usb_device_get_libusb_device ()

+
gconstpointer
+spice_usb_device_get_libusb_device (const SpiceUsbDevice *device);
+

Finds the libusb_device associated with the device +.

+
+

Parameters

+
+++++ + + + + + +

device

SpiceUsbDevice to get the descriptor information of

 
+
+
+

Returns

+

the libusb_device associated to SpiceUsbDevice.

+

[transfer none]

+
+

Since: 0.27

+
+
+
+

Types and Values

+
+

struct SpiceUsbDeviceManager

+
struct SpiceUsbDeviceManager;
+

The SpiceUsbDeviceManager struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceUsbDeviceManagerClass

+
struct SpiceUsbDeviceManagerClass {
+    GObjectClass parent_class;
+
+    /* signals */
+    void (*device_added) (SpiceUsbDeviceManager *manager,
+                          SpiceUsbDevice *device);
+    void (*device_removed) (SpiceUsbDeviceManager *manager,
+                            SpiceUsbDevice *device);
+    void (*auto_connect_failed) (SpiceUsbDeviceManager *manager,
+                                 SpiceUsbDevice *device, GError *error);
+    void (*device_error) (SpiceUsbDeviceManager *manager,
+                          SpiceUsbDevice *device, GError *error);
+};
+
+

Class structure for SpiceUsbDeviceManager.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

device_added ()

Signal class handler for the “device-added” signal.

 

device_removed ()

Signal class handler for the “device-removed” signal.

 

auto_connect_failed ()

Signal class handler for the “auto-connect-failed” signal.

 

device_error ()

Signal class handler for the “device_error” signal.

 
+
+
+
+
+

SpiceUsbDevice

+
typedef struct _SpiceUsbDevice SpiceUsbDevice;
+

The SpiceUsbDevice struct is opaque and cannot be accessed directly.

+
+
+
+

Property Details

+
+

The “auto-connect” property

+
  “auto-connect”             gboolean
+

Set this to TRUE to automatically redirect newly plugged in device.

+

Note when SpiceGtkSession's auto-usbredir property is TRUE, this +property is controlled by SpiceGtkSession.

+

Flags: Read / Write

+

Default value: FALSE

+
+
+
+

The “auto-connect-filter” property

+
  “auto-connect-filter”      gchar *
+

Set a string specifying a filter to use to determine which USB devices +to autoconnect when plugged in, a filter consists of one or more rules. +Where each rule has the form of:

+

class +,vendor +,product +,version +,allow +

+

Use -1 for class +/vendor +/product +/version + to accept any value.

+

And the rules themselves are concatenated like this:

+

rule1 +|rule2 +|rule3 +

+

The default setting filters out HID (class 0x03) USB devices from auto +connect and auto connects anything else. Note the explicit allow rule at +the end, this is necessary since by default all devices without a +matching filter rule will not auto-connect.

+

Filter strings in this format can be easily created with the RHEV-M +USB filter editor tool.

+

Flags: Read / Write / Construct

+

Default value: "0x03,-1,-1,-1,0|-1,-1,-1,-1,1"

+
+
+
+

The “free-channels” property

+
  “free-channels”            gint
+

The number of available channels for redirecting USB devices.

+

Flags: Read

+

Allowed values: >= 0

+

Default value: 0

+
+
+
+

The “redirect-on-connect” property

+
  “redirect-on-connect”      gchar *
+

Set a string specifying a filter selecting USB devices to automatically +redirect after a Spice connection has been established.

+

See “auto-connect-filter” for the filter string +format.

+

Flags: Read / Write

+

Default value: NULL

+
+
+
+

The “session” property

+
  “session”                  SpiceSession *
+

SpiceSession this SpiceUsbDeviceManager is associated with

+

Flags: Read / Write / Construct Only

+
+
+
+

Signal Details

+
+

The “auto-connect-failed” signal

+
void
+user_function (SpiceUsbDeviceManager *manager,
+               SpiceUsbDevice        *device,
+               GError                *error,
+               gpointer               user_data)
+

The “auto-connect-failed” signal is emitted +whenever the auto-connect property is true, and a newly plugged in +device could not be auto-connected.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager that emitted the signal

 

device

SpiceUsbDevice boxed object corresponding to the device which failed to auto connect

 

error

GError describing the reason why the autoconnect failed

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “device-added” signal

+
void
+user_function (SpiceUsbDeviceManager *manager,
+               SpiceUsbDevice        *device,
+               gpointer               user_data)
+

The “device-added” signal is emitted whenever +a new USB device has been plugged in.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager that emitted the signal

 

device

SpiceUsbDevice boxed object corresponding to the added device

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “device-error” signal

+
void
+user_function (SpiceUsbDeviceManager *manager,
+               SpiceUsbDevice        *device,
+               GError                *error,
+               gpointer               user_data)
+

The “device-error” signal is emitted whenever an +error happens which causes a device to no longer be available to the +guest.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

manager

SpiceUsbDeviceManager that emitted the signal

 

device

SpiceUsbDevice boxed object corresponding to the device which has an error

 

error

GError describing the error

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+

The “device-removed” signal

+
void
+user_function (SpiceUsbDeviceManager *manager,
+               SpiceUsbDevice        *device,
+               gpointer               user_data)
+

The “device-removed” signal is emitted whenever +an USB device has been removed.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

manager

the SpiceUsbDeviceManager that emitted the signal

 

device

SpiceUsbDevice boxed object corresponding to the removed device

 

user_data

user data set when the signal handler was connected.

 
+
+

Flags: Run First

+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceUsbredirChannel.html b/doc/reference/html/SpiceUsbredirChannel.html new file mode 100644 index 0000000..1b38166 --- /dev/null +++ b/doc/reference/html/SpiceUsbredirChannel.html @@ -0,0 +1,119 @@ + + + + +USB Redirection Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

USB Redirection Channel

+

USB Redirection Channel — usb redirection

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceUsbredirChannel
structSpiceUsbredirChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpiceUsbredirChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The Spice protocol defines a set of messages to redirect USB devices +from the Spice client to the VM. This channel handles these messages.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct SpiceUsbredirChannel

+
struct SpiceUsbredirChannel;
+

The SpiceUsbredirChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceUsbredirChannelClass

+
struct SpiceUsbredirChannelClass {
+    SpiceChannelClass parent_class;
+
+    /* signals */
+};
+
+

Class structure for SpiceUsbredirChannel.

+
+

Members

+
+++++ + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/SpiceWebdavChannel.html b/doc/reference/html/SpiceWebdavChannel.html new file mode 100644 index 0000000..b30177a --- /dev/null +++ b/doc/reference/html/SpiceWebdavChannel.html @@ -0,0 +1,126 @@ + + + + +WebDAV Channel: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

WebDAV Channel

+

WebDAV Channel — exports a directory

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Types and Values

+
++++ + + + + + + + + + + +
structSpiceWebdavChannel
structSpiceWebdavChannelClass
+
+
+

Object Hierarchy

+
    GObject
+    ╰── SpiceChannel
+        ╰── SpicePortChannel
+            ╰── SpiceWebdavChannel
+
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

The "webdav" channel exports a directory to the guest for file +manipulation (read/write/copy etc). The underlying protocol is +implemented using WebDAV (RFC 4918).

+

By default, the shared directory is the one associated with GLib +G_USER_DIRECTORY_PUBLIC_SHARE. You can specify a different +directory with SpiceSession “shared-dir” property.

+
+
+

Functions

+

+
+
+

Types and Values

+
+

struct SpiceWebdavChannel

+
struct SpiceWebdavChannel;
+

The SpiceWebdavChannel struct is opaque and should not be accessed directly.

+
+
+
+

struct SpiceWebdavChannelClass

+
struct SpiceWebdavChannelClass {
+    SpicePortChannelClass parent_class;
+};
+
+

Class structure for SpiceWebdavChannel.

+
+

Members

+
+++++ + +
+
+
+
+
+

See Also

+

SpiceChannel

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/annotation-glossary.html b/doc/reference/html/annotation-glossary.html new file mode 100644 index 0000000..31c3a62 --- /dev/null +++ b/doc/reference/html/annotation-glossary.html @@ -0,0 +1,67 @@ + + + + +Annotation Glossary: Spice-GTK Reference Manual + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

A

+
allow-none
+

NULL is OK, both for passing and for returning.

+
array
+

Parameter points to an array of items.

+

C

+
closure
+

This parameter is a 'user_data', for callbacks; many bindings can pass NULL here.

+

E

+
element-type
+

Generics and defining elements of containers and arrays.

+

S

+
scope async
+

The callback is valid until first called.

+
scope call
+

The callback is valid only during the call to the method.

+
Stable
+

The intention of a Stable interface is to enable arbitrary third parties to +develop applications to these interfaces, release them, and have confidence that +they will run on all minor releases of the product (after the one in which the +interface was introduced, and within the same major release). Even at a major +release, incompatible changes are expected to be rare, and to have strong +justifications. +

+

T

+
transfer container
+

Free data container after the code is done.

+
transfer full
+

Free data after the code is done.

+
transfer none
+

Don't free data after the code is done.

+
+ + + \ No newline at end of file diff --git a/doc/reference/html/api-index-deprecated.html b/doc/reference/html/api-index-deprecated.html new file mode 100644 index 0000000..bc8d5b3 --- /dev/null +++ b/doc/reference/html/api-index-deprecated.html @@ -0,0 +1,87 @@ + + + + +Index of deprecated symbols: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/reference/html/api-index-full.html b/doc/reference/html/api-index-full.html new file mode 100644 index 0000000..94e4ece --- /dev/null +++ b/doc/reference/html/api-index-full.html @@ -0,0 +1,1195 @@ + + + + +API Index: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+API Index

+

A

+
+SpiceAudio, struct in SpiceAudio +
+
+
+SpiceAudio:main-context, object property in SpiceAudio +
+
+
+SpiceAudio:session, object property in SpiceAudio +
+
+
+SpiceAudioClass, struct in SpiceAudio +
+
+
+spice_audio_get, function in SpiceAudio +
+
+
+spice_audio_new, function in SpiceAudio +
+
+

C

+
+SpiceChannel, struct in SpiceChannel +
+
+
+SpiceChannel::channel-event, object signal in SpiceChannel +
+
+
+SpiceChannel::open-fd, object signal in SpiceChannel +
+
+
+SpiceChannel:channel-id, object property in SpiceChannel +
+
+
+SpiceChannel:channel-type, object property in SpiceChannel +
+
+
+SpiceChannel:spice-session, object property in SpiceChannel +
+
+
+SpiceChannel:total-read-bytes, object property in SpiceChannel +
+
+
+SpiceChannelClass, struct in SpiceChannel +
+
+
+SpiceChannelEvent, enum in SpiceChannel +
+
+
+spice_channel_connect, function in SpiceChannel +
+
+
+spice_channel_destroy, function in SpiceChannel +
+
+
+spice_channel_disconnect, function in SpiceChannel +
+
+
+spice_channel_flush_async, function in SpiceChannel +
+
+
+spice_channel_flush_finish, function in SpiceChannel +
+
+
+spice_channel_get_error, function in SpiceChannel +
+
+
+spice_channel_new, function in SpiceChannel +
+
+
+spice_channel_open_fd, function in SpiceChannel +
+
+
+spice_channel_set_capability, function in SpiceChannel +
+
+
+spice_channel_string_to_type, function in SpiceChannel +
+
+
+spice_channel_test_capability, function in SpiceChannel +
+
+
+spice_channel_test_common_capability, function in SpiceChannel +
+
+
+spice_channel_type_to_string, function in SpiceChannel +
+
+
+SpiceClientError, enum in SpiceSession +
+
+
+SPICE_CLIENT_ERROR, macro in SpiceSession +
+
+
+spice_client_error_quark, function in SpiceSession +
+
+
+SpiceCursorChannel, struct in SpiceCursorChannel +
+
+
+SpiceCursorChannel::cursor-hide, object signal in SpiceCursorChannel +
+
+
+SpiceCursorChannel::cursor-move, object signal in SpiceCursorChannel +
+
+
+SpiceCursorChannel::cursor-reset, object signal in SpiceCursorChannel +
+
+
+SpiceCursorChannel::cursor-set, object signal in SpiceCursorChannel +
+
+
+SpiceCursorChannelClass, struct in SpiceCursorChannel +
+
+

D

+
+SpiceDisplayChannel, struct in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel::display-invalidate, object signal in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel::display-mark, object signal in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel::display-primary-create, object signal in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel::display-primary-destroy, object signal in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel::gl-draw, object signal in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel:gl-scanout, object property in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel:height, object property in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel:monitors, object property in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel:monitors-max, object property in SpiceDisplayChannel +
+
+
+SpiceDisplayChannel:width, object property in SpiceDisplayChannel +
+
+
+SpiceDisplayChannelClass, struct in SpiceDisplayChannel +
+
+
+SpiceDisplayKeyEvent, enum in SpiceDisplay +
+
+
+SpiceDisplayMonitorConfig, struct in SpiceDisplayChannel +
+
+
+SpiceDisplayPrimary, struct in SpiceDisplayChannel +
+
+
+spice_display_change_preferred_compression, function in SpiceDisplayChannel +
+
+
+spice_display_get_gl_scanout, function in SpiceDisplayChannel +
+
+
+spice_display_get_grab_keys, function in SpiceDisplay +
+
+
+spice_display_get_pixbuf, function in SpiceDisplay +
+
+
+spice_display_get_primary, function in SpiceDisplayChannel +
+
+
+spice_display_gl_draw_done, function in SpiceDisplayChannel +
+
+
+spice_display_mouse_ungrab, function in SpiceDisplay +
+
+
+spice_display_new, function in SpiceDisplay +
+
+
+spice_display_new_with_monitor, function in SpiceDisplay +
+
+
+spice_display_send_keys, function in SpiceDisplay +
+
+
+spice_display_set_grab_keys, function in SpiceDisplay +
+
+

F

+
+SpiceFileTransferTask::finished, object signal in SpiceFileTransferTask +
+
+
+SpiceFileTransferTask:cancellable, object property in SpiceFileTransferTask +
+
+
+SpiceFileTransferTask:channel, object property in SpiceFileTransferTask +
+
+
+SpiceFileTransferTask:file, object property in SpiceFileTransferTask +
+
+
+SpiceFileTransferTask:id, object property in SpiceFileTransferTask +
+
+
+SpiceFileTransferTask:progress, object property in SpiceFileTransferTask +
+
+
+spice_file_transfer_task_cancel, function in SpiceFileTransferTask +
+
+
+spice_file_transfer_task_get_filename, function in SpiceFileTransferTask +
+
+
+spice_file_transfer_task_get_progress, function in SpiceFileTransferTask +
+
+

G

+
+spice_get_option_group, function in SpiceSession +
+
+
+SpiceGlScanout, struct in SpiceDisplayChannel +
+
+
+spice_gl_scanout_free, function in SpiceDisplayChannel +
+
+
+SpiceGrabSequence, struct in SpiceDisplay +
+
+
+spice_grab_sequence_as_string, function in SpiceDisplay +
+
+
+spice_grab_sequence_copy, function in SpiceDisplay +
+
+
+spice_grab_sequence_free, function in SpiceDisplay +
+
+
+spice_grab_sequence_new, function in SpiceDisplay +
+
+
+spice_grab_sequence_new_from_string, function in SpiceDisplay +
+
+
+SPICE_GTK_CHECK_VERSION, macro in Version Information +
+
+
+SPICE_GTK_MAJOR_VERSION, macro in Version Information +
+
+
+SPICE_GTK_MICRO_VERSION, macro in Version Information +
+
+
+SPICE_GTK_MINOR_VERSION, macro in Version Information +
+
+
+spice_gtk_session_copy_to_guest, function in SpiceGtkSession +
+
+
+spice_gtk_session_get, function in SpiceGtkSession +
+
+
+spice_gtk_session_paste_from_guest, function in SpiceGtkSession +
+
+

I

+
+SpiceInputsChannel, struct in SpiceInputsChannel +
+
+
+SpiceInputsChannel::inputs-modifiers, object signal in SpiceInputsChannel +
+
+
+SpiceInputsChannel:key-modifiers, object property in SpiceInputsChannel +
+
+
+SpiceInputsChannelClass, struct in SpiceInputsChannel +
+
+
+SpiceInputsLock, enum in SpiceInputsChannel +
+
+
+spice_inputs_button_press, function in SpiceInputsChannel +
+
+
+spice_inputs_button_release, function in SpiceInputsChannel +
+
+
+spice_inputs_key_press, function in SpiceInputsChannel +
+
+
+spice_inputs_key_press_and_release, function in SpiceInputsChannel +
+
+
+spice_inputs_key_release, function in SpiceInputsChannel +
+
+
+spice_inputs_motion, function in SpiceInputsChannel +
+
+
+spice_inputs_position, function in SpiceInputsChannel +
+
+
+spice_inputs_set_key_locks, function in SpiceInputsChannel +
+
+

M

+
+SpiceMainChannel, struct in SpiceMainChannel +
+
+
+SpiceMainChannel::main-agent-update, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-grab, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-release, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-request, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-selection, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-selection-grab, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-selection-release, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-clipboard-selection-request, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::main-mouse-update, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::migration-started, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel::new-file-transfer, object signal in SpiceMainChannel +
+
+
+SpiceMainChannel:agent-caps-0, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:agent-connected, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:color-depth, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:disable-animation, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:disable-display-align, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:disable-display-position, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:disable-font-smooth, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:disable-wallpaper, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:max-clipboard, object property in SpiceMainChannel +
+
+
+SpiceMainChannel:mouse-mode, object property in SpiceMainChannel +
+
+
+SpiceMainChannelClass, struct in SpiceMainChannel +
+
+
+spice_main_agent_test_capability, function in SpiceMainChannel +
+
+
+spice_main_clipboard_grab, function in SpiceMainChannel +
+
+
+spice_main_clipboard_notify, function in SpiceMainChannel +
+
+
+spice_main_clipboard_release, function in SpiceMainChannel +
+
+
+spice_main_clipboard_request, function in SpiceMainChannel +
+
+
+spice_main_clipboard_selection_grab, function in SpiceMainChannel +
+
+
+spice_main_clipboard_selection_notify, function in SpiceMainChannel +
+
+
+spice_main_clipboard_selection_release, function in SpiceMainChannel +
+
+
+spice_main_clipboard_selection_request, function in SpiceMainChannel +
+
+
+spice_main_file_copy_async, function in SpiceMainChannel +
+
+
+spice_main_file_copy_finish, function in SpiceMainChannel +
+
+
+spice_main_request_mouse_mode, function in SpiceMainChannel +
+
+
+spice_main_send_monitor_config, function in SpiceMainChannel +
+
+
+spice_main_set_display, function in SpiceMainChannel +
+
+
+spice_main_set_display_enabled, function in SpiceMainChannel +
+
+
+spice_main_update_display, function in SpiceMainChannel +
+
+
+spice_main_update_display_enabled, function in SpiceMainChannel +
+
+

P

+
+SpicePlaybackChannel, struct in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel::playback-data, object signal in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel::playback-get-delay, object signal in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel::playback-start, object signal in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel::playback-stop, object signal in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel:min-latency, object property in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel:mute, object property in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel:nchannels, object property in SpicePlaybackChannel +
+
+
+SpicePlaybackChannel:volume, object property in SpicePlaybackChannel +
+
+
+SpicePlaybackChannelClass, struct in SpicePlaybackChannel +
+
+
+spice_playback_channel_set_delay, function in SpicePlaybackChannel +
+
+
+SpicePortChannel, struct in SpicePortChannel +
+
+
+SpicePortChannel::port-data, object signal in SpicePortChannel +
+
+
+SpicePortChannel::port-event, object signal in SpicePortChannel +
+
+
+SpicePortChannel:port-name, object property in SpicePortChannel +
+
+
+SpicePortChannel:port-opened, object property in SpicePortChannel +
+
+
+SpicePortChannelClass, struct in SpicePortChannel +
+
+
+spice_port_event, function in SpicePortChannel +
+
+
+spice_port_write_async, function in SpicePortChannel +
+
+
+spice_port_write_finish, function in SpicePortChannel +
+
+

R

+
+SpiceRecordChannel, struct in SpiceRecordChannel +
+
+
+SpiceRecordChannel::record-start, object signal in SpiceRecordChannel +
+
+
+SpiceRecordChannel::record-stop, object signal in SpiceRecordChannel +
+
+
+SpiceRecordChannel:mute, object property in SpiceRecordChannel +
+
+
+SpiceRecordChannel:nchannels, object property in SpiceRecordChannel +
+
+
+SpiceRecordChannel:volume, object property in SpiceRecordChannel +
+
+
+SpiceRecordChannelClass, struct in SpiceRecordChannel +
+
+
+spice_record_send_data, function in SpiceRecordChannel +
+
+

S

+
+SpiceSession, struct in SpiceSession +
+
+
+SpiceSession::channel-destroy, object signal in SpiceSession +
+
+
+SpiceSession::channel-new, object signal in SpiceSession +
+
+
+SpiceSession::mm-time-reset, object signal in SpiceSession +
+
+
+SpiceSession:ca, object property in SpiceSession +
+
+
+SpiceSession:ca-file, object property in SpiceSession +
+
+
+SpiceSession:cache-size, object property in SpiceSession +
+
+
+SpiceSession:cert-subject, object property in SpiceSession +
+
+
+SpiceSession:ciphers, object property in SpiceSession +
+
+
+SpiceSession:client-sockets, object property in SpiceSession +
+
+
+SpiceSession:color-depth, object property in SpiceSession +
+
+
+SpiceSession:disable-effects, object property in SpiceSession +
+
+
+SpiceSession:enable-audio, object property in SpiceSession +
+
+
+SpiceSession:enable-smartcard, object property in SpiceSession +
+
+
+SpiceSession:enable-usbredir, object property in SpiceSession +
+
+
+SpiceSession:glz-window-size, object property in SpiceSession +
+
+
+SpiceSession:host, object property in SpiceSession +
+
+
+SpiceSession:inhibit-keyboard-grab, object property in SpiceSession +
+
+
+SpiceSession:migration-state, object property in SpiceSession +
+
+
+SpiceSession:name, object property in SpiceSession +
+
+
+SpiceSession:password, object property in SpiceSession +
+
+
+SpiceSession:port, object property in SpiceSession +
+
+
+SpiceSession:preferred-compression, object property in SpiceSession +
+
+
+SpiceSession:protocol, object property in SpiceSession +
+
+
+SpiceSession:proxy, object property in SpiceSession +
+
+
+SpiceSession:pubkey, object property in SpiceSession +
+
+
+SpiceSession:read-only, object property in SpiceSession +
+
+
+SpiceSession:secure-channels, object property in SpiceSession +
+
+
+SpiceSession:share-dir-ro, object property in SpiceSession +
+
+
+SpiceSession:shared-dir, object property in SpiceSession +
+
+
+SpiceSession:smartcard-certificates, object property in SpiceSession +
+
+
+SpiceSession:smartcard-db, object property in SpiceSession +
+
+
+SpiceSession:tls-port, object property in SpiceSession +
+
+
+SpiceSession:unix-path, object property in SpiceSession +
+
+
+SpiceSession:uri, object property in SpiceSession +
+
+
+SpiceSession:username, object property in SpiceSession +
+
+
+SpiceSession:uuid, object property in SpiceSession +
+
+
+SpiceSession:verify, object property in SpiceSession +
+
+
+SpiceSessionClass, struct in SpiceSession +
+
+
+SpiceSessionMigration, enum in SpiceSession +
+
+
+SpiceSessionVerify, enum in SpiceSession +
+
+
+spice_session_connect, function in SpiceSession +
+
+
+spice_session_disconnect, function in SpiceSession +
+
+
+spice_session_get_channels, function in SpiceSession +
+
+
+spice_session_get_proxy_uri, function in SpiceSession +
+
+
+spice_session_get_read_only, function in SpiceSession +
+
+
+spice_session_has_channel_type, function in SpiceSession +
+
+
+spice_session_is_for_migration, function in SpiceSession +
+
+
+spice_session_new, function in SpiceSession +
+
+
+spice_session_open_fd, function in SpiceSession +
+
+
+spice_set_session_option, function in SpiceSession +
+
+
+SpiceSmartcardChannel, struct in SpiceSmartcardChannel +
+
+
+SpiceSmartcardChannelClass, struct in SpiceSmartcardChannel +
+
+
+SpiceSmartcardManager, struct in SpiceSmartcardManager +
+
+
+SpiceSmartcardManager::card-inserted, object signal in SpiceSmartcardManager +
+
+
+SpiceSmartcardManager::card-removed, object signal in SpiceSmartcardManager +
+
+
+SpiceSmartcardManager::reader-added, object signal in SpiceSmartcardManager +
+
+
+SpiceSmartcardManager::reader-removed, object signal in SpiceSmartcardManager +
+
+
+SpiceSmartcardManagerClass, struct in SpiceSmartcardManager +
+
+
+SpiceSmartcardReader, struct in SpiceSmartcardManager +
+
+
+spice_smartcard_manager_get, function in SpiceSmartcardManager +
+
+
+spice_smartcard_manager_get_readers, function in SpiceSmartcardManager +
+
+
+spice_smartcard_manager_insert_card, function in SpiceSmartcardManager +
+
+
+spice_smartcard_manager_remove_card, function in SpiceSmartcardManager +
+
+
+spice_smartcard_reader_insert_card, function in SpiceSmartcardManager +
+
+
+spice_smartcard_reader_is_software, function in SpiceSmartcardManager +
+
+
+spice_smartcard_reader_remove_card, function in SpiceSmartcardManager +
+
+

U

+
+SpiceURI, struct in SpiceURI +
+
+
+SpiceURIClass, struct in SpiceURI +
+
+
+spice_uri_get_hostname, function in SpiceURI +
+
+
+spice_uri_get_password, function in SpiceURI +
+
+
+spice_uri_get_port, function in SpiceURI +
+
+
+spice_uri_get_scheme, function in SpiceURI +
+
+
+spice_uri_get_user, function in SpiceURI +
+
+
+spice_uri_set_hostname, function in SpiceURI +
+
+
+spice_uri_set_password, function in SpiceURI +
+
+
+spice_uri_set_port, function in SpiceURI +
+
+
+spice_uri_set_scheme, function in SpiceURI +
+
+
+spice_uri_set_user, function in SpiceURI +
+
+
+spice_uri_to_string, function in SpiceURI +
+
+
+SpiceUsbDevice, struct in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager, struct in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager::auto-connect-failed, object signal in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager::device-added, object signal in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager::device-error, object signal in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager::device-removed, object signal in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager:auto-connect, object property in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager:auto-connect-filter, object property in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager:free-channels, object property in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager:redirect-on-connect, object property in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManager:session, object property in SpiceUsbDeviceManager +
+
+
+SpiceUsbDeviceManagerClass, struct in SpiceUsbDeviceManager +
+
+
+SpiceUsbredirChannel, struct in SpiceUsbredirChannel +
+
+
+SpiceUsbredirChannelClass, struct in SpiceUsbredirChannel +
+
+
+spice_usb_device_get_description, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_get_libusb_device, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_can_redirect_device, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_connect_device_async, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_connect_device_finish, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_disconnect_device, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_disconnect_device_async, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_disconnect_device_finish, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_get, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_get_devices, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_get_devices_with_filter, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_is_device_connected, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_manager_is_redirecting, function in SpiceUsbDeviceManager +
+
+
+spice_usb_device_widget_new, function in SpiceUsbDeviceWidget +
+
+
+spice_util_get_version_string, function in Utilities +
+
+
+spice_util_set_debug, function in Utilities +
+
+
+spice_uuid_to_string, function in Utilities +
+
+

W

+
+SpiceWebdavChannel, struct in SpiceWebdavChannel +
+
+
+SpiceWebdavChannelClass, struct in SpiceWebdavChannel +
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/api-reference.html b/doc/reference/html/api-reference.html new file mode 100644 index 0000000..6d7fe86 --- /dev/null +++ b/doc/reference/html/api-reference.html @@ -0,0 +1,110 @@ + + + + +Part I. API Reference: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+Part I. API Reference

+
+

Table of Contents

+
+
Object Hierarchy
+
Session and Channels Objects, from spice-client-glib
+
+
+Spice Session — handles connection details, and active channels +
+
+Spice Channel — the base channel class +
+
+Cursor Channel — update cursor shape and position +
+
+Display Channel — remote display area +
+
+Inputs Channel — control the server mouse and keyboard +
+
+Main Channel — the main Spice channel +
+
+Playback Channel — audio stream for playback +
+
+Record Channel — audio stream for recording +
+
+Smartcard Channel — smartcard authentication +
+
+USB Redirection Channel — usb redirection +
+
+Port Channel — private communication channel +
+
+WebDAV Channel — exports a directory +
+
+
GTK Widget, from spice-client-gtk
+
+
+Spice GTK Session — handles GTK connection details +
+
+Spice Display — a GTK display widget +
+
+Spice USB device selection widget — USB device selection widget +
+
+
Application Support, from spice-client-glib
+
+
+Spice Audio — a helper to play and to record audio channels +
+
+Spice Smartcard Manager — smartcard management +
+
+Spice USB Manager — USB device management +
+
+Utilities — version and debugging functions +
+
+Version Information — Spice-Gtk version checking +
+
+SpiceURI — URIs handling +
+
+File Transfer Task — Monitoring file transfers +
+
+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/application-support.html b/doc/reference/html/application-support.html new file mode 100644 index 0000000..3304b3a --- /dev/null +++ b/doc/reference/html/application-support.html @@ -0,0 +1,52 @@ + + + + +Application Support, from spice-client-glib: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+Application Support, from spice-client-glib

+
+
+Spice Audio — a helper to play and to record audio channels +
+
+Spice Smartcard Manager — smartcard management +
+
+Spice USB Manager — USB device management +
+
+Utilities — version and debugging functions +
+
+Version Information — Spice-Gtk version checking +
+
+SpiceURI — URIs handling +
+
+File Transfer Task — Monitoring file transfers +
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/ch01.html b/doc/reference/html/ch01.html new file mode 100644 index 0000000..7ba6ef5 --- /dev/null +++ b/doc/reference/html/ch01.html @@ -0,0 +1,58 @@ + + + + +Object Hierarchy: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+Object Hierarchy

+
+    GObject
+    ├── SpiceAudio
+    ├── SpiceChannel
+    │   ├── SpiceCursorChannel
+    │   ├── SpiceDisplayChannel
+    │   ├── SpiceInputsChannel
+    │   ├── SpiceMainChannel
+    │   ├── SpicePlaybackChannel
+    │   ├── SpiceRecordChannel
+    │   ├── SpiceSmartcardChannel
+    │   ├── SpiceUsbredirChannel
+    │   ╰── SpicePortChannel
+    │       ╰── SpiceWebdavChannel
+    ├── SpiceSession
+    ├── SpiceSmartcardManager
+    ├── SpiceUsbDeviceManager
+    ╰── SpiceFileTransferTask
+    GEnum
+    ├── SpiceChannelEvent
+    ╰── SpiceSessionMigration
+    GBoxed
+    ├── SpiceGrabSequence
+    ├── SpiceUsbDevice
+    ╰── SpiceGlScanout
+    GFlags
+    ├── SpiceInputsLock
+    ╰── SpiceSessionVerify
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/ch02.html b/doc/reference/html/ch02.html new file mode 100644 index 0000000..eb93937 --- /dev/null +++ b/doc/reference/html/ch02.html @@ -0,0 +1,67 @@ + + + + +Session and Channels Objects, from spice-client-glib: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+Session and Channels Objects, from spice-client-glib

+
+
+Spice Session — handles connection details, and active channels +
+
+Spice Channel — the base channel class +
+
+Cursor Channel — update cursor shape and position +
+
+Display Channel — remote display area +
+
+Inputs Channel — control the server mouse and keyboard +
+
+Main Channel — the main Spice channel +
+
+Playback Channel — audio stream for playback +
+
+Record Channel — audio stream for recording +
+
+Smartcard Channel — smartcard authentication +
+
+USB Redirection Channel — usb redirection +
+
+Port Channel — private communication channel +
+
+WebDAV Channel — exports a directory +
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/ch03.html b/doc/reference/html/ch03.html new file mode 100644 index 0000000..066212c --- /dev/null +++ b/doc/reference/html/ch03.html @@ -0,0 +1,40 @@ + + + + +GTK Widget, from spice-client-gtk: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+GTK Widget, from spice-client-gtk

+
+
+Spice GTK Session — handles GTK connection details +
+
+Spice Display — a GTK display widget +
+
+Spice USB device selection widget — USB device selection widget +
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/home.png b/doc/reference/html/home.png new file mode 100644 index 0000000000000000000000000000000000000000..9346b336a784463192c7daab5133a3673dd69845 GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefRMbARQqaxysz9Q}BI-m)~Y zggoA|1V*z2{cQ=d;!=?fvu4~`n82RKrk1UubNXTJj1GP|o-=>$A29f{JgJ9K`^t{Q z-oWs>M&_hvT&MjX@T4-&sBW+1^4oB5G4r2q!qGktZ!n*!)hjrjd0_4L6;4%u<}orJ u%Vo~x?#i!!ww+1OGuHe}T=cKQUzn^_t)8|WlnDbmjKR~@&t;ucLK6T + + + +Spice-GTK Reference Manual: Spice-GTK Reference Manual + + + + + + + +
+
+
+
+
+
+
I. API Reference
+
+
Object Hierarchy
+
Session and Channels Objects, from spice-client-glib
+
+
+Spice Session — handles connection details, and active channels +
+
+Spice Channel — the base channel class +
+
+Cursor Channel — update cursor shape and position +
+
+Display Channel — remote display area +
+
+Inputs Channel — control the server mouse and keyboard +
+
+Main Channel — the main Spice channel +
+
+Playback Channel — audio stream for playback +
+
+Record Channel — audio stream for recording +
+
+Smartcard Channel — smartcard authentication +
+
+USB Redirection Channel — usb redirection +
+
+Port Channel — private communication channel +
+
+WebDAV Channel — exports a directory +
+
+
GTK Widget, from spice-client-gtk
+
+
+Spice GTK Session — handles GTK connection details +
+
+Spice Display — a GTK display widget +
+
+Spice USB device selection widget — USB device selection widget +
+
+
Application Support, from spice-client-glib
+
+
+Spice Audio — a helper to play and to record audio channels +
+
+Spice Smartcard Manager — smartcard management +
+
+Spice USB Manager — USB device management +
+
+Utilities — version and debugging functions +
+
+Version Information — Spice-Gtk version checking +
+
+SpiceURI — URIs handling +
+
+File Transfer Task — Monitoring file transfers +
+
+
+
Object Hierarchy
+
API Index
+
Index of deprecated symbols
+
Annotation Glossary
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/left-insensitive.png b/doc/reference/html/left-insensitive.png new file mode 100644 index 0000000000000000000000000000000000000000..3269393a7f72af744a772c437bd7b3976c23709d GIT binary patch literal 395 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefH0HbvDJm`3=E7Co-U3d7N^fnTIWJ3j{^~q!iyia4kV=mdU|Jhfgdm;SLIpiYJ7wv^kjFiECCc&8T30!RG0~&BG=X zlu#U4@Z`))V`EG9e^NqDr#{!5k|)wT* zYTNt0`@q%TAD$){%#eQ?;$^ly8}yZCU%T~u0XM^%t?f#e znB*EuLv2rP%K3BMvFO}YmnR}KSgH;`EHL$)^!tH~iBxZ#h^zJi*#P5Xb6B50U@nx2 mU;T=yfcwnSOsS9SKd{M#MlNkCuvG>I8-u5-pUXO@geCx5`k@p6 literal 0 HcmV?d00001 diff --git a/doc/reference/html/left.png b/doc/reference/html/left.png new file mode 100644 index 0000000000000000000000000000000000000000..2abde032b0c98b756b12d380da4318205cd78470 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefRMaSLay~*pwMJb7sn8b(^oI8=R24v(*CjE{-BFv z0BhvLm?o9(UC{-Ci?lD?Ve-7-xypA!PTC(0^;>UheG4Altep3@`rO0#Rjs1)RxCLr zE5mee>7m*=%yEk+GVvGkRy0O&*&MTd5SjH(lgq~7r%6oRW$l1p-*S}iC>@fyDsz%y z`UIW8^Ao=maGhj3E8{7Cd_qof`K4oa->23`>&M2+XBtd2J`8jogQu&X%Q~loCIG_? BVG#fT literal 0 HcmV?d00001 diff --git a/doc/reference/html/object-tree.html b/doc/reference/html/object-tree.html new file mode 100644 index 0000000..5ce1740 --- /dev/null +++ b/doc/reference/html/object-tree.html @@ -0,0 +1,58 @@ + + + + +Object Hierarchy: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+

+Object Hierarchy

+
+    GObject
+    ├── SpiceAudio
+    ├── SpiceChannel
+    │   ├── SpiceCursorChannel
+    │   ├── SpiceDisplayChannel
+    │   ├── SpiceInputsChannel
+    │   ├── SpiceMainChannel
+    │   ├── SpicePlaybackChannel
+    │   ├── SpiceRecordChannel
+    │   ├── SpiceSmartcardChannel
+    │   ├── SpiceUsbredirChannel
+    │   ╰── SpicePortChannel
+    │       ╰── SpiceWebdavChannel
+    ├── SpiceSession
+    ├── SpiceSmartcardManager
+    ├── SpiceUsbDeviceManager
+    ╰── SpiceFileTransferTask
+    GEnum
+    ├── SpiceChannelEvent
+    ╰── SpiceSessionMigration
+    GBoxed
+    ├── SpiceGrabSequence
+    ├── SpiceUsbDevice
+    ╰── SpiceGlScanout
+    GFlags
+    ├── SpiceInputsLock
+    ╰── SpiceSessionVerify
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/right-insensitive.png b/doc/reference/html/right-insensitive.png new file mode 100644 index 0000000000000000000000000000000000000000..4c95785b907b978f36674cd98bf5302669c15c1b GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefG`u!(zUX23=E7+o-U3d7N^fn+URvSL8NuRG*{E) z?#-+97X-^pidQ*u@StO1(S@7g8g>nnA24$?ty?)cmuaa|Y>ez2*_Ia?6HP4j{3LIs zTr!s1ao_Sz^~3e4zRJGAjKZGn=XP#)Wmuo-QN>teTzzI!&R*jMI^Oa#7_ukLYdicf zOx;1mb-rt04s-c|uIH8fnX}$)XJa^0_-F3(pA%=sGI<|(n_*&=yYt96+n5InXn_GN+EraJI9q(O+n{6MQKErp&KxRvpfn0xh z`sSMqH(2Z%?kaFBTf06W^y=UDA9gR9YrwNS*1pjB((0K%&+SbAx3`XA&dKZ}j*nX7 QfdRze>FVdQ&MBb@09|aA9{>OV literal 0 HcmV?d00001 diff --git a/doc/reference/html/right.png b/doc/reference/html/right.png new file mode 100644 index 0000000000000000000000000000000000000000..76260ec8865f4e13cd269ec62eccd78a33adba3c GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefRMbR+#PqI2*V^#7sn8b(^oI8=W9$9IsUQVezxzH zy`G{eu0`y#boSlU-NAlQG~=D)BPJG4k(^0qdDa(AdQvI0d|vJT=i7_<_D6`Cy?Dm; zP0@1EeB~D|O$oQe*sxL-P;q{2UCr}fN-o#M~tpZzsGyfNz46SZlIJCbKH zZQscEqpOfBCPDgx + + + +Spice Display: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice Display

+

Spice Display — a GTK display widget

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+SpiceDisplay * + +spice_display_new () +
+SpiceDisplay * + +spice_display_new_with_monitor () +
+void + +spice_display_mouse_ungrab () +
+void + +spice_display_set_grab_keys () +
+SpiceGrabSequence * + +spice_display_get_grab_keys () +
+void + +spice_display_send_keys () +
+GdkPixbuf * + +spice_display_get_pixbuf () +
+SpiceGrabSequence * + +spice_grab_sequence_new () +
+SpiceGrabSequence * + +spice_grab_sequence_new_from_string () +
+SpiceGrabSequence * + +spice_grab_sequence_copy () +
+void + +spice_grab_sequence_free () +
+gchar * + +spice_grab_sequence_as_string () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
enumSpiceDisplayKeyEvent
 SpiceGrabSequence
+
+
+

Object Hierarchy

+
    GBoxed
+    ╰── SpiceGrabSequence
+
+
+
+

Includes

+
#include <spice-client-gtk.h>
+
+
+
+

Description

+

A GTK widget that displays a SPICE server. It sends keyboard/mouse +events and can also share clipboard...

+

Arbitrary key events can be sent thanks to spice_display_send_keys().

+

The widget will optionally grab the keyboard and the mouse when +focused if the properties “grab-keyboard” and +“grab-mouse” are TRUE respectively. It can be +ungrabbed with spice_display_mouse_ungrab(), and by setting a key +combination with spice_display_set_grab_keys().

+

Finally, spice_display_get_pixbuf() will take a screenshot of the +current display and return an GdkPixbuf (that you can then easily +save to disk).

+
+
+

Functions

+
+

spice_display_new ()

+
SpiceDisplay *
+spice_display_new (SpiceSession *session,
+                   int channel_id);
+

Creates a new SpiceDisplay widget.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

a SpiceSession

 

channel_id

the display channel ID to associate with SpiceDisplay

 
+
+
+

Returns

+

a new SpiceDisplay widget.

+
+
+
+
+

spice_display_new_with_monitor ()

+
SpiceDisplay *
+spice_display_new_with_monitor (SpiceSession *session,
+                                gint channel_id,
+                                gint monitor_id);
+

Creates a new SpiceDisplay widget associated with the monitor id.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

session

a SpiceSession

 

channel_id

the display channel ID to associate with SpiceDisplay

 

monitor_id

the monitor id within the display channel

 
+
+
+

Returns

+

a new SpiceDisplay widget.

+
+

Since: 0.13

+
+
+
+

spice_display_mouse_ungrab ()

+
void
+spice_display_mouse_ungrab (SpiceDisplay *display);
+

Ungrab the mouse.

+
+

Parameters

+
+++++ + + + + + +

display

a SpiceDisplay

 
+
+
+
+
+

spice_display_set_grab_keys ()

+
void
+spice_display_set_grab_keys (SpiceDisplay *display,
+                             SpiceGrabSequence *seq);
+

Set the key combination to grab/ungrab the keyboard. The default is +"Control L + Alt L".

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

display

the display widget

 

seq

key sequence.

[transfer none]
+
+
+
+
+

spice_display_get_grab_keys ()

+
SpiceGrabSequence *
+spice_display_get_grab_keys (SpiceDisplay *display);
+

Finds the current grab key combination for the display +.

+
+

Parameters

+
+++++ + + + + + +

display

the display widget

 
+
+
+

Returns

+

the current grab key combination.

+

[transfer none]

+
+
+
+
+

spice_display_send_keys ()

+
void
+spice_display_send_keys (SpiceDisplay *display,
+                         const guint *keyvals,
+                         int nkeyvals,
+                         SpiceDisplayKeyEvent kind);
+

Send keyval press/release events to the display.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +

display

The SpiceDisplay

 

keyvals

Keyval array.

[array length=nkeyvals]

nkeyvals

Length of keyvals

 

kind

SpiceDisplayKeyEvent action

 
+
+
+
+
+

spice_display_get_pixbuf ()

+
GdkPixbuf *
+spice_display_get_pixbuf (SpiceDisplay *display);
+

Take a screenshot of the display.

+
+

Parameters

+
+++++ + + + + + +

display

a SpiceDisplay

 
+
+
+

Returns

+

a GdkPixbuf with the screenshot image buffer.

+

[transfer full]

+
+
+
+
+

spice_grab_sequence_new ()

+
SpiceGrabSequence *
+spice_grab_sequence_new (guint nkeysyms,
+                         guint *keysyms);
+

Creates a new grab sequence from a list of keysym values

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

nkeysyms

length of keysyms +

 

keysyms

the keysym values.

[array length=nkeysyms]
+
+
+

Returns

+

a new grab sequence object.

+

[transfer full]

+
+
+
+
+

spice_grab_sequence_new_from_string ()

+
SpiceGrabSequence *
+spice_grab_sequence_new_from_string (const gchar *str);
+

Creates a new SpiceGrabSequence from the string representation.

+
+

Parameters

+
+++++ + + + + + +

str

a string of '+' separated key names (ex: "Control_L+Alt_L")

 
+
+
+

Returns

+

a new SpiceGrabSequence.

+
+
+
+
+

spice_grab_sequence_copy ()

+
SpiceGrabSequence *
+spice_grab_sequence_copy (SpiceGrabSequence *sequence);
+

Creates a copy of the sequence +.

+
+

Parameters

+
+++++ + + + + + +

sequence

sequence to copy

 
+
+
+

Returns

+

a copy of sequence +.

+

[transfer full]

+
+
+
+
+

spice_grab_sequence_free ()

+
void
+spice_grab_sequence_free (SpiceGrabSequence *sequence);
+

Free sequence +.

+
+

Parameters

+
+++++ + + + + + +

sequence

a SpiceGrabSequence

 
+
+
+
+
+

spice_grab_sequence_as_string ()

+
gchar *
+spice_grab_sequence_as_string (SpiceGrabSequence *sequence);
+

Creates a string representing the sequence +.

+
+

Parameters

+
+++++ + + + + + +

sequence

a SpiceGrabSequence

 
+
+
+

Returns

+

a newly allocated string representing the key sequence.

+

[transfer full]

+
+
+
+
+

Types and Values

+
+

enum SpiceDisplayKeyEvent

+

Constants for key events.

+
+

Members

+
+++++ + + + + + + + + + + + + + + + + + +

SPICE_DISPLAY_KEY_EVENT_PRESS

+

key press

+
 

SPICE_DISPLAY_KEY_EVENT_RELEASE

+

key release

+
 

SPICE_DISPLAY_KEY_EVENT_CLICK

+

key click (press and release)

+
 
+
+
+
+
+

SpiceGrabSequence

+
typedef struct {
+} SpiceGrabSequence;
+
+

An opaque type that represents a grab sequence.

+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk-SpiceGtkSession.html b/doc/reference/html/spice-gtk-SpiceGtkSession.html new file mode 100644 index 0000000..90d3483 --- /dev/null +++ b/doc/reference/html/spice-gtk-SpiceGtkSession.html @@ -0,0 +1,190 @@ + + + + +Spice GTK Session: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice GTK Session

+

Spice GTK Session — handles GTK connection details

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+SpiceGtkSession * + +spice_gtk_session_get () +
+void + +spice_gtk_session_copy_to_guest () +
+void + +spice_gtk_session_paste_from_guest () +
+
+
+

Includes

+
#include <spice-client-gtk.h>
+
+
+
+

Description

+

The SpiceGtkSession class is the spice-client-gtk counter part of +SpiceSession. It contains functionality which should be handled per +session rather then per SpiceDisplay (one session can have multiple +displays), but which cannot live in SpiceSession as it depends on +GTK. For example the clipboard functionality.

+

There should always be a 1:1 relation between SpiceGtkSession objects +and SpiceSession objects. Therefor there is no spice_gtk_session_new, +instead there is spice_gtk_session_get() which ensures this 1:1 relation.

+

Client and guest clipboards will be shared automatically if +“auto-clipboard” is set to TRUE. Alternatively, you +can send / receive clipboard data from client to guest with +spice_gtk_session_copy_to_guest() / spice_gtk_session_paste_from_guest().

+
+
+

Functions

+
+

spice_gtk_session_get ()

+
SpiceGtkSession *
+spice_gtk_session_get (SpiceSession *session);
+

Gets the SpiceGtkSession associated with the passed in SpiceSession. +A new SpiceGtkSession instance will be created the first time this +function is called for a certain SpiceSession.

+

Note that this function returns a weak reference, which should not be used +after the SpiceSession itself has been unref-ed by the caller.

+
+

Parameters

+
+++++ + + + + + +

session

SpiceSession for which to get the SpiceGtkSession

 
+
+
+

Returns

+

a weak reference to the SpiceGtkSession associated with the passed in SpiceSession

+

Since 0.8.

+

[transfer none]

+
+
+
+
+

spice_gtk_session_copy_to_guest ()

+
void
+spice_gtk_session_copy_to_guest (SpiceGtkSession *self);
+

Copy client-side clipboard to guest clipboard.

+

Since 0.8

+
+

Parameters

+
+++++ + + + + + +

self

SpiceGtkSession

 
+
+
+
+
+

spice_gtk_session_paste_from_guest ()

+
void
+spice_gtk_session_paste_from_guest (SpiceGtkSession *self);
+

Copy guest clipboard to client-side clipboard.

+

Since 0.8

+
+

Parameters

+
+++++ + + + + + +

self

SpiceGtkSession

 
+
+
+
+
+

Types and Values

+
+
+

See Also

+

SpiceSession, and the GTK widget SpiceDisplay

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk-SpiceURI.html b/doc/reference/html/spice-gtk-SpiceURI.html new file mode 100644 index 0000000..3cd6039 --- /dev/null +++ b/doc/reference/html/spice-gtk-SpiceURI.html @@ -0,0 +1,527 @@ + + + + +SpiceURI: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

SpiceURI

+

SpiceURI — URIs handling

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
const gchar * + +spice_uri_get_scheme () +
+void + +spice_uri_set_scheme () +
const gchar * + +spice_uri_get_hostname () +
+void + +spice_uri_set_hostname () +
+guint + +spice_uri_get_port () +
+void + +spice_uri_set_port () +
const gchar * + +spice_uri_get_user () +
+void + +spice_uri_set_user () +
const gchar * + +spice_uri_get_password () +
+void + +spice_uri_set_password () +
+gchar * + +spice_uri_to_string () +
+
+
+

Types and Values

+
++++ + + + + + + + + + + +
 SpiceURIClass
 SpiceURI
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

A SpiceURI represents a (parsed) URI.

+
+
+

Functions

+
+

spice_uri_get_scheme ()

+
const gchar *
+spice_uri_get_scheme (SpiceURI *uri);
+

Gets uri +'s scheme.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

uri +'s scheme.

+
+

Since: 0.24

+
+
+
+

spice_uri_set_scheme ()

+
void
+spice_uri_set_scheme (SpiceURI *uri,
+                      const gchar *scheme);
+

Sets uri +'s scheme to scheme +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SpiceURI

 

scheme

the scheme

 
+
+

Since: 0.24

+
+
+
+

spice_uri_get_hostname ()

+
const gchar *
+spice_uri_get_hostname (SpiceURI *uri);
+

Gets uri +'s hostname.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

uri +'s hostname.

+
+

Since: 0.24

+
+
+
+

spice_uri_set_hostname ()

+
void
+spice_uri_set_hostname (SpiceURI *uri,
+                        const gchar *hostname);
+

Sets uri +'s hostname to hostname +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SpiceURI

 

hostname

the hostname

 
+
+

Since: 0.24

+
+
+
+

spice_uri_get_port ()

+
guint
+spice_uri_get_port (SpiceURI *uri);
+

Gets uri +'s port.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

uri +'s port.

+
+

Since: 0.24

+
+
+
+

spice_uri_set_port ()

+
void
+spice_uri_set_port (SpiceURI *uri,
+                    guint port);
+

Sets uri +'s port to port +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SpiceURI

 

port

the port

 
+
+

Since: 0.24

+
+
+
+

spice_uri_get_user ()

+
const gchar *
+spice_uri_get_user (SpiceURI *uri);
+

Gets uri +'s user.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

uri +'s user.

+
+

Since: 0.24

+
+
+
+

spice_uri_set_user ()

+
void
+spice_uri_set_user (SpiceURI *uri,
+                    const gchar *user);
+

Sets uri +'s user to user +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SpiceURI

 

user

the user, or NULL.

 
+
+

Since: 0.24

+
+
+
+

spice_uri_get_password ()

+
const gchar *
+spice_uri_get_password (SpiceURI *uri);
+

Gets uri +'s password.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

uri +'s password.

+
+

Since: 0.24

+
+
+
+

spice_uri_set_password ()

+
void
+spice_uri_set_password (SpiceURI *uri,
+                        const gchar *password);
+

Sets uri +'s password to password +.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

uri

a SpiceURI

 

password

the password, or NULL.

 
+
+

Since: 0.24

+
+
+
+

spice_uri_to_string ()

+
gchar *
+spice_uri_to_string (SpiceURI *uri);
+

Returns a string representing uri +.

+
+

Parameters

+
+++++ + + + + + +

uri

a SpiceURI

 
+
+
+

Returns

+

a string representing uri +, which the caller must free.

+
+

Since: 0.24

+
+
+
+

Types and Values

+
+

SpiceURIClass

+
typedef struct _SpiceURIClass SpiceURIClass;
+

The SpiceURIClass struct is opaque and cannot be accessed directly. +It is class structure for SpiceURI.

+
+
+
+

SpiceURI

+
typedef struct _SpiceURI SpiceURI;
+

The SpiceURI struct is opaque and cannot be accessed directly.

+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk-SpiceUsbDeviceWidget.html b/doc/reference/html/spice-gtk-SpiceUsbDeviceWidget.html new file mode 100644 index 0000000..7f3c786 --- /dev/null +++ b/doc/reference/html/spice-gtk-SpiceUsbDeviceWidget.html @@ -0,0 +1,115 @@ + + + + +Spice USB device selection widget: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Spice USB device selection widget

+

Spice USB device selection widget — USB device selection widget

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + +
+GtkWidget * + +spice_usb_device_widget_new () +
+
+
+

Includes

+
#include <spice-client-gtk.h>
+
+
+
+

Description

+

SpiceUsbDeviceWidget is a gtk widget which apps can use to easily +add an UI to select USB devices to redirect (or unredirect).

+
+
+

Functions

+
+

spice_usb_device_widget_new ()

+
GtkWidget *
+spice_usb_device_widget_new (SpiceSession *session,
+                             const gchar *device_format_string);
+

Creates a new widget to control USB redirection.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

session

SpiceSession for which to widget will control USB redirection

 

device_format_string

String passed to +spice_usb_device_get_description().

[allow-none]
+
+
+

Returns

+

a new SpiceUsbDeviceWidget instance

+
+
+
+
+

Types and Values

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk-Utilities.html b/doc/reference/html/spice-gtk-Utilities.html new file mode 100644 index 0000000..49fc20a --- /dev/null +++ b/doc/reference/html/spice-gtk-Utilities.html @@ -0,0 +1,158 @@ + + + + +Utilities: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Utilities

+

Utilities — version and debugging functions

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Functions

+
++++ + + + + + + + + + + + + + + +
+void + +spice_util_set_debug () +
const gchar * + +spice_util_get_version_string () +
+gchar * + +spice_uuid_to_string () +
+
+
+

Includes

+
#include <spice-client.h>
+
+
+
+

Description

+

Various functions for debugging and informational purposes.

+
+
+

Functions

+
+

spice_util_set_debug ()

+
void
+spice_util_set_debug (gboolean enabled);
+

Enable or disable Spice-GTK debugging messages.

+
+

Parameters

+
+++++ + + + + + +

enabled

TRUE or FALSE

 
+
+
+
+
+

spice_util_get_version_string ()

+
const gchar *
+spice_util_get_version_string (void);
+

Gets the version string

+
+

Returns

+

Spice-GTK version as a const string.

+
+
+
+
+

spice_uuid_to_string ()

+
gchar *
+spice_uuid_to_string (const guint8 uuid[16]);
+

Creates a string representation of uuid +, of the form +"06e023d5-86d8-420e-8103-383e4566087a"

+
+

Parameters

+
+++++ + + + + + +

uuid

UUID byte array

 
+
+
+

Returns

+

A string that should be freed with g_free().

+
+

Since: 0.22

+
+
+
+

Types and Values

+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk-Version-Information.html b/doc/reference/html/spice-gtk-Version-Information.html new file mode 100644 index 0000000..1bb6024 --- /dev/null +++ b/doc/reference/html/spice-gtk-Version-Information.html @@ -0,0 +1,149 @@ + + + + +Version Information: Spice-GTK Reference Manual + + + + + + + + + + + + + + + + +
+
+
+ + +
+

Version Information

+

Version Information — Spice-Gtk version checking

+
+
+

Functions

+
++++ + + + + +
#define +SPICE_GTK_CHECK_VERSION() +
+
+
+

Types and Values

+
++++ + + + + + + + + + + + + + + +
#defineSPICE_GTK_MAJOR_VERSION
#defineSPICE_GTK_MICRO_VERSION
#defineSPICE_GTK_MINOR_VERSION
+
+
+

Includes

+
#include <spice-version.h>
+
+
+
+

Description

+

Spice-Gtk provides macros to check the version of the library +at compile-time

+
+
+

Functions

+
+

SPICE_GTK_CHECK_VERSION()

+
#define             SPICE_GTK_CHECK_VERSION(major, minor, micro)
+

Compile-time version checking. Evaluates to TRUE if the version +of Spice-Gtk is greater than the required one.

+
+

Parameters

+
+++++ + + + + + + + + + + + + + + + + + +

major

required major version

 

minor

required minor version

 

micro

required micro version

 
+
+

Since: 0.24

+
+
+
+

Types and Values

+
+

SPICE_GTK_MAJOR_VERSION

+
#define SPICE_GTK_MAJOR_VERSION              (0)
+
+

Spice-Gtk major version component (e.g. 1 if version is 1.2.3)

+

Since: 0.24

+
+
+
+

SPICE_GTK_MICRO_VERSION

+
#define SPICE_GTK_MICRO_VERSION              (0)
+
+

Spice-Gtk micro version component (e.g. 3 if version is 1.2.3)

+

Since: 0.24

+
+
+
+

SPICE_GTK_MINOR_VERSION

+
#define SPICE_GTK_MINOR_VERSION              (32)
+
+

Spice-Gtk minor version component (e.g. 2 if version is 1.2.3)

+

Since: 0.24

+
+
+
+ + + \ No newline at end of file diff --git a/doc/reference/html/spice-gtk.devhelp2 b/doc/reference/html/spice-gtk.devhelp2 new file mode 100644 index 0000000..93305ff --- /dev/null +++ b/doc/reference/html/spice-gtk.devhelp2 @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/reference/html/style.css b/doc/reference/html/style.css new file mode 100644 index 0000000..3675420 --- /dev/null +++ b/doc/reference/html/style.css @@ -0,0 +1,479 @@ +body +{ + font-family: cantarell, sans-serif; +} +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + background: rgba(238, 238, 236, 0.5); + border: solid 1px rgb(238, 238, 236); + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + /* fallback for no rgba support */ + background: #e6f3ff; + border: solid 1px #729fcf; + background: rgba(114, 159, 207, 0.1); + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.informaltable table +{ + border-collapse: separate; + border-spacing: 1em 0.3em; + border: none; +} + +div.informaltable table td, div.informaltable table th +{ + vertical-align: top; +} + +.function_type, +.variable_type, +.property_type, +.signal_type, +.parameter_name, +.struct_member_name, +.union_member_name, +.define_keyword, +.datatype_keyword, +.typedef_keyword +{ + text-align: right; +} + +/* dim non-primary columns */ +.c_punctuation, +.function_type, +.variable_type, +.property_type, +.signal_type, +.define_keyword, +.datatype_keyword, +.typedef_keyword, +.property_flags, +.signal_flags, +.parameter_annotations, +.enum_member_annotations, +.struct_member_annotations, +.union_member_annotations +{ + color: #888a85; +} + +.function_type a, +.function_type a:visited, +.function_type a:hover, +.property_type a, +.property_type a:visited, +.property_type a:hover, +.signal_type a, +.signal_type a:visited, +.signal_type a:hover, +.signal_flags a, +.signal_flags a:visited, +.signal_flags a:hover +{ + color: #729fcf; +} + +td p +{ + margin: 0.25em; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +h4 +{ + color: #555753; + margin-top: 1em; + margin-bottom: 1em; +} + +hr +{ + /* tango:aluminium 1 */ + color: #d3d7cf; + background: #d3d7cf; + border: none 0px; + height: 1px; + clear: both; + margin: 2.0em 0em 2.0em 0em; +} + +dl.toc dt +{ + padding-bottom: 0.25em; +} + +dl.toc > dt +{ + padding-top: 0.25em; + padding-bottom: 0.25em; + font-weight: bold; +} + +dl.toc > dl +{ + padding-bottom: 0.5em; +} + +.parameter +{ + font-style: normal; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.informalfigure, +.figure +{ + margin: 1em; +} + +.informalexample, +.example +{ + margin-top: 1em; + margin-bottom: 1em; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + background: rgba(252, 175, 62, 0.1); + border-color: #ffb04f; + border-color: rgba(252, 175, 62, 0.2); +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + background: rgba(138, 226, 52, 0.1); + border-color: #abf562; + border-color: rgba(138, 226, 52, 0.2); +} +div.blockquote +{ + border-color: #eeeeec; +} +.note, .warning, div.blockquote +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; + margin: 2em; +} +.note p, .warning p +{ + margin: 0; +} + +div.warning h3.title, +div.note h3.title +{ + display: none; +} + +p + div.section +{ + margin-top: 1em; +} + +div.refnamediv, +div.refsynopsisdiv, +div.refsect1, +div.refsect2, +div.toc, +div.section +{ + margin-bottom: 1em; +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.lineart +{ + color: #d3d7cf; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-weight: normal; +} + +.structfield +{ + font-style: normal; + font-weight: normal; +} + +acronym,abbr +{ + border-bottom: 1px dotted gray; +} + +/* code listings */ + +.listing_code .programlisting .normal, +.listing_code .programlisting .normal a, +.listing_code .programlisting .number, +.listing_code .programlisting .cbracket, +.listing_code .programlisting .symbol { color: #555753; } +.listing_code .programlisting .comment, +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .function, +.listing_code .programlisting .function a, +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ +.listing_code .programlisting .keyword, +.listing_code .programlisting .usertype, +.listing_code .programlisting .type, +.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + border: solid 1px rgba(114, 159, 207, 0.2); + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + background: rgba(114, 159, 207, 0.2); + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; + background: rgba(114, 159, 207, 0.1); +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; + background: none; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + +@media screen { + /* these have a as a first child, but since there are no parent selectors + * we can't use that. */ + a.footnote + { + position: relative; + top: 0em ! important; + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + display: inline-block; + position: relative; + top:-5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 2.5em; + padding-bottom: 500px; + max-width: 60em; + } + p + { + max-width: 60em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + background: #e2e2e2; + border-bottom: solid 1px #babdb6; + border-spacing: 5px; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + z-index: 10; + } + table.navigation#top td + { + padding-left: 6px; + padding-right: 6px; + } + .navigation a, .navigation a:visited + { + /* tango:sky blue 3 */ + color: #204a87; + } + .navigation a:hover + { + /* tango:sky blue 2 */ + color: #3465a4; + } + td.shortcuts + { + /* tango:sky blue 2 */ + color: #3465a4; + font-size: 80%; + white-space: nowrap; + } + td.shortcuts .dim + { + color: #babdb6; + } + .navigation .title + { + font-size: 80%; + max-width: none; + margin: 0px; + font-weight: normal; + } +} +@media screen and (min-width: 60em) { + /* screen larger than 60em */ + body { margin: auto; } +} +@media screen and (max-width: 60em) { + /* screen less than 60em */ + #nav_hierarchy { display: none; } + #nav_interfaces { display: none; } + #nav_prerequisites { display: none; } + #nav_derived_interfaces { display: none; } + #nav_implementations { display: none; } + #nav_child_properties { display: none; } + #nav_style_properties { display: none; } + #nav_index { display: none; } + #nav_glossary { display: none; } + .gallery_image { display: none; } + .property_flags { display: none; } + .signal_flags { display: none; } + .parameter_annotations { display: none; } + .enum_member_annotations { display: none; } + .struct_member_annotations { display: none; } + .union_member_annotations { display: none; } + /* now that a column is hidden, optimize space */ + col.parameters_name { width: auto; } + col.parameters_description { width: auto; } + col.struct_members_name { width: auto; } + col.struct_members_description { width: auto; } + col.enum_members_name { width: auto; } + col.enum_members_description { width: auto; } + col.union_members_name { width: auto; } + col.union_members_description { width: auto; } + .listing_lines { display: none; } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + background: #e2e2e2; + border: solid 1px #babdb6; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + diff --git a/doc/reference/html/up-insensitive.png b/doc/reference/html/up-insensitive.png new file mode 100644 index 0000000000000000000000000000000000000000..f40498606db349a7321cf6b470523e836ee7ac2e GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefG~@Ex#w@70gTL^E{-7zACwHGSRJaopUzr*FR_KPpkxheNzTDP+%{a~ox zRb6~e-_l%s#;V|Jw-)bO$G_X=4F`Y7SBoCzyjAZQ8BPW>ywAP8?pbBsZ|wt?+h6S6&uqY)kkMnwQQEd@7k`4t@sCCO z@7MoiEI4Q_#IB70vhu7Ab+>SXLxu@LWH Qzz|~aboFyt=akR{08E^fv;Y7A literal 0 HcmV?d00001 diff --git a/doc/reference/html/up.png b/doc/reference/html/up.png new file mode 100644 index 0000000000000000000000000000000000000000..80b4b37e997d69b2e128bc3090bc447ccb74bbe9 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHjTefRFevZLys@4W>+6GUE!tU04Ii{0w_tkMIDB?rA5 zttYTN + +]> + + + Spice-GTK Reference Manual + + + + + API Reference + + Object Hierarchy + + + + + Session and Channels Objects, from spice-client-glib + + + + + + + + + + + + + + + + + GTK Widget, from spice-client-gtk + + + + + + + Application Support, from spice-client-glib + + + + + + + + + + + + + Object Hierarchy + + + + API Index + + + + + Index of deprecated symbols + + + + + diff --git a/doc/reference/spice-gtk-overrides.txt b/doc/reference/spice-gtk-overrides.txt new file mode 100644 index 0000000..e69de29 diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt new file mode 100644 index 0000000..df58297 --- /dev/null +++ b/doc/reference/spice-gtk-sections.txt @@ -0,0 +1,527 @@ +
+channel-playback +SpicePlaybackChannel +SpicePlaybackChannel +SpicePlaybackChannelClass +spice_playback_channel_set_delay + +SPICE_PLAYBACK_CHANNEL +SPICE_IS_PLAYBACK_CHANNEL +SPICE_TYPE_PLAYBACK_CHANNEL +spice_playback_channel_get_type +SPICE_PLAYBACK_CHANNEL_CLASS +SPICE_IS_PLAYBACK_CHANNEL_CLASS +SPICE_PLAYBACK_CHANNEL_GET_CLASS + +SpicePlaybackChannelPrivate +spice_playback_channel_get_latency +spice_playback_channel_is_active +spice_playback_channel_sync_latency +
+ +
+spice-session +SpiceSession +SpiceSession +SpiceSessionClass +spice_session_new +spice_session_connect +spice_session_open_fd +spice_session_disconnect +spice_session_get_channels +spice_session_get_read_only +spice_session_has_channel_type +spice_session_get_proxy_uri +spice_session_is_for_migration + +SpiceSessionMigration +SpiceSessionVerify +spice_get_option_group +spice_set_session_option + +SpiceClientError +SPICE_CLIENT_ERROR +spice_client_error_quark + +SPICE_SESSION +SPICE_IS_SESSION +SPICE_TYPE_SESSION +spice_session_get_type +SPICE_SESSION_CLASS +SPICE_IS_SESSION_CLASS +SPICE_SESSION_GET_CLASS +SPICE_TYPE_SESSION_VERIFY +spice_session_verify_get_type +SPICE_TYPE_SESSION_MIGRATION +spice_session_migration_get_type + +SpiceSessionPrivate +SPICE_CLIENT_USB_DEVICE_LOST +SPICE_CLIENT_USB_DEVICE_REJECTED +
+ +
+channel-main +SpiceMainChannel +SpiceMainChannel +SpiceMainChannelClass + +spice_main_set_display +spice_main_set_display_enabled +spice_main_update_display +spice_main_update_display_enabled +spice_main_send_monitor_config +spice_main_agent_test_capability +spice_main_request_mouse_mode +spice_main_clipboard_selection_grab +spice_main_clipboard_selection_notify +spice_main_clipboard_selection_release +spice_main_clipboard_selection_request +spice_main_clipboard_grab +spice_main_clipboard_release +spice_main_clipboard_notify +spice_main_clipboard_request +spice_main_file_copy_async +spice_main_file_copy_finish + +SPICE_MAIN_CHANNEL +SPICE_IS_MAIN_CHANNEL +SPICE_TYPE_MAIN_CHANNEL +spice_main_channel_get_type +SPICE_MAIN_CHANNEL_CLASS +SPICE_IS_MAIN_CHANNEL_CLASS +SPICE_MAIN_CHANNEL_GET_CLASS + +SpiceMainChannelPrivate +
+ +
+spice-channel +SpiceChannel +SpiceChannelEvent +SpiceChannel +SpiceChannelClass + +spice_channel_new +spice_channel_destroy +spice_channel_connect +spice_channel_open_fd +spice_channel_disconnect +spice_channel_test_capability +spice_channel_test_common_capability +spice_channel_type_to_string +spice_channel_string_to_type +spice_channel_set_capability +spice_channel_flush_async +spice_channel_flush_finish +spice_channel_get_error + +SPICE_TYPE_CHANNEL_EVENT +spice_channel_event_get_type +SPICE_CHANNEL +SPICE_IS_CHANNEL +SPICE_TYPE_CHANNEL +spice_channel_get_type +SPICE_CHANNEL_CLASS +SPICE_IS_CHANNEL_CLASS +SPICE_CHANNEL_GET_CLASS + +SpiceMsgIn +SpiceMsgOut +SpiceChannelClassPrivate +SpiceChannelPrivate +spice_msg_handler +spice_msg_in +spice_msg_out +
+ +
+spice-audio +SpiceAudio +SpiceAudio +SpiceAudioClass + +spice_audio_get +spice_audio_new + +SPICE_AUDIO +SPICE_IS_AUDIO +SPICE_TYPE_AUDIO +spice_audio_get_type +SPICE_AUDIO_CLASS +SPICE_IS_AUDIO_CLASS +SPICE_AUDIO_GET_CLASS + +SpiceAudioPrivate +
+ +
+channel-display +SpiceDisplayChannel +SpiceDisplayChannel +SpiceDisplayChannelClass +SpiceDisplayMonitorConfig +SpiceDisplayPrimary +SpiceGlScanout + +spice_display_get_gl_scanout +spice_display_gl_draw_done +spice_display_get_primary +spice_display_change_preferred_compression +spice_gl_scanout_free + +SPICE_DISPLAY_CHANNEL +SPICE_IS_DISPLAY_CHANNEL +SPICE_TYPE_DISPLAY_CHANNEL +spice_display_channel_get_type +SPICE_DISPLAY_CHANNEL_CLASS +SPICE_IS_DISPLAY_CHANNEL_CLASS +SPICE_DISPLAY_CHANNEL_GET_CLASS +SPICE_TYPE_GL_SCANOUT +spice_gl_scanout_get_type + +SpiceDisplayChannelPrivate +
+ +
+channel-cursor +SpiceCursorChannel +SpiceCursorChannel +SpiceCursorChannelClass + +SPICE_CURSOR_CHANNEL +SPICE_IS_CURSOR_CHANNEL +SPICE_TYPE_CURSOR_CHANNEL +spice_cursor_channel_get_type +SPICE_CURSOR_CHANNEL_CLASS +SPICE_IS_CURSOR_CHANNEL_CLASS +SPICE_CURSOR_CHANNEL_GET_CLASS + +SpiceCursorChannelPrivate +
+ +
+channel-record +SpiceRecordChannel +SpiceRecordChannel +SpiceRecordChannelClass + +spice_record_send_data + +SPICE_RECORD_CHANNEL +SPICE_IS_RECORD_CHANNEL +SPICE_TYPE_RECORD_CHANNEL +spice_record_channel_get_type +SPICE_RECORD_CHANNEL_CLASS +SPICE_IS_RECORD_CHANNEL_CLASS +SPICE_RECORD_CHANNEL_GET_CLASS + +SpiceRecordChannelPrivate +
+ +
+channel-inputs +SpiceInputsChannel +SpiceInputsChannel +SpiceInputsChannelClass +SpiceInputsLock + +spice_inputs_motion +spice_inputs_position +spice_inputs_button_press +spice_inputs_button_release +spice_inputs_key_press +spice_inputs_key_press_and_release +spice_inputs_key_release +spice_inputs_set_key_locks + +SPICE_TYPE_INPUTS_LOCK +spice_inputs_lock_get_type +SPICE_INPUTS_CHANNEL +SPICE_IS_INPUTS_CHANNEL +SPICE_TYPE_INPUTS_CHANNEL +spice_inputs_channel_get_type +SPICE_INPUTS_CHANNEL_CLASS +SPICE_IS_INPUTS_CHANNEL_CLASS +SPICE_INPUTS_CHANNEL_GET_CLASS + +SpiceInputsChannelPrivate +
+ +
+channel-smartcard +SpiceSmartcardChannel +SpiceSmartcardChannel +SpiceSmartcardChannelClass + +SPICE_SMARTCARD_CHANNEL +SPICE_IS_SMARTCARD_CHANNEL +SPICE_TYPE_SMARTCARD_CHANNEL +spice_smartcard_channel_get_type +SPICE_SMARTCARD_CHANNEL_CLASS +SPICE_IS_SMARTCARD_CHANNEL_CLASS +SPICE_SMARTCARD_CHANNEL_GET_CLASS + +SpiceSmartcardChannelPrivate +
+ +
+smartcard-manager +SpiceSmartcardManager +SpiceSmartcardManager +SpiceSmartcardManagerClass +SpiceSmartcardReader + +spice_smartcard_manager_get +spice_smartcard_manager_get_readers +spice_smartcard_manager_insert_card +spice_smartcard_manager_remove_card + +spice_smartcard_reader_is_software +spice_smartcard_reader_insert_card +spice_smartcard_reader_remove_card + +SPICE_SMARTCARD_MANAGER +SPICE_IS_SMARTCARD_MANAGER +SPICE_TYPE_SMARTCARD_MANAGER +spice_smartcard_manager_get_type +SPICE_SMARTCARD_MANAGER_CLASS +SPICE_IS_SMARTCARD_MANAGER_CLASS +SPICE_SMARTCARD_MANAGER_GET_CLASS +SPICE_TYPE_SMARTCARD_READER +spice_smartcard_reader_get_type + +SpiceSmartcardManagerPrivate +
+ +
+channel-usbredir +SpiceUsbredirChannel +SpiceUsbredirChannel +SpiceUsbredirChannelClass + +SPICE_USBREDIR_CHANNEL +SPICE_IS_USBREDIR_CHANNEL +SPICE_TYPE_USBREDIR_CHANNEL +spice_usbredir_channel_get_type +SPICE_USBREDIR_CHANNEL_CLASS +SPICE_IS_USBREDIR_CHANNEL_CLASS +SPICE_USBREDIR_CHANNEL_GET_CLASS + +SpiceUsbredirChannelPrivate +
+ +
+usb-device-manager +SpiceUsbDeviceManager +SpiceUsbDeviceManager +SpiceUsbDeviceManagerClass + +spice_usb_device_manager_get +spice_usb_device_manager_get_devices +spice_usb_device_manager_get_devices_with_filter +spice_usb_device_manager_is_device_connected +spice_usb_device_manager_is_redirecting +spice_usb_device_manager_can_redirect_device +spice_usb_device_manager_connect_device_async +spice_usb_device_manager_connect_device_finish +spice_usb_device_manager_disconnect_device +spice_usb_device_manager_disconnect_device_async +spice_usb_device_manager_disconnect_device_finish + +SpiceUsbDevice +spice_usb_device_get_description +spice_usb_device_get_libusb_device + +SPICE_USB_DEVICE_MANAGER +SPICE_IS_USB_DEVICE_MANAGER +SPICE_TYPE_USB_DEVICE +SPICE_TYPE_USB_DEVICE_MANAGER +spice_usb_device_manager_get_type +spice_usb_device_get_type +SPICE_USB_DEVICE_MANAGER_CLASS +SPICE_IS_USB_DEVICE_MANAGER_CLASS +SPICE_USB_DEVICE_MANAGER_GET_CLASS + +SpiceUsbDeviceManagerPrivate +
+ +
+spice-gtk-session +SpiceGtkSession +spice_gtk_session_get +spice_gtk_session_copy_to_guest +spice_gtk_session_paste_from_guest + +SPICE_GTK_SESSION +SPICE_IS_GTK_SESSION +SPICE_TYPE_GTK_SESSION +spice_gtk_session_get_type +SPICE_GTK_SESSION_CLASS +SPICE_IS_GTK_SESSION_CLASS +SPICE_GTK_SESSION_GET_CLASS + +SpiceGtkSessionPrivate +
+ +
+spice-widget +SpiceDisplay +SpiceDisplayKeyEvent +spice_display_new +spice_display_new_with_monitor +spice_display_mouse_ungrab +spice_display_set_grab_keys +spice_display_get_grab_keys +spice_display_send_keys +spice_display_get_pixbuf + +SpiceGrabSequence +spice_grab_sequence_new +spice_grab_sequence_new_from_string +spice_grab_sequence_copy +spice_grab_sequence_free +spice_grab_sequence_as_string + +SPICE_DISPLAY +SPICE_IS_DISPLAY +SPICE_TYPE_DISPLAY +spice_display_get_type +SPICE_DISPLAY_CLASS +SPICE_IS_DISPLAY_CLASS +SPICE_DISPLAY_GET_CLASS +SPICE_TYPE_GRAB_SEQUENCE +spice_grab_sequence_get_type +SPICE_TYPE_DISPLAY_KEY_EVENT +spice_display_key_event_get_type + +SpiceDisplayPrivate +
+ +
+usb-device-widget +SpiceUsbDeviceWidget + +spice_usb_device_widget_new + +SPICE_USB_DEVICE_WIDGET +SPICE_IS_USB_DEVICE_WIDGET +spice_usb_device_widget_get_type +SPICE_USB_DEVICE_WIDGET_CLASS +SPICE_IS_USB_DEVICE_WIDGET_CLASS +SPICE_USB_DEVICE_WIDGET_GET_CLASS +SPICE_TYPE_USB_DEVICE_WIDGET + +SpiceUsbDeviceWidgetPrivate +SpiceGtkBox +SpiceGtkBoxClass +
+ +
+spice-util +spice_util_set_debug +spice_util_get_version_string +spice_uuid_to_string + +SPICE_DEBUG +spice_util_get_debug +SPICE_RESERVED_PADDING +SPICE_DEPRECATED_FOR +spice_g_signal_connect_object +SPICE_DEPRECATED +SPICE_GNUC_DEPRECATED_FOR +
+ +
+spice-version +SPICE_GTK_CHECK_VERSION +SPICE_GTK_MAJOR_VERSION +SPICE_GTK_MICRO_VERSION +SPICE_GTK_MINOR_VERSION +
+ +
+channel-port +SpicePortChannel +SpicePortChannel +SpicePortChannelClass + +spice_port_event +spice_port_write_async +spice_port_write_finish + +SPICE_PORT_CHANNEL +SPICE_IS_PORT_CHANNEL +SPICE_TYPE_PORT_CHANNEL +spice_port_channel_get_type +SPICE_PORT_CHANNEL_CLASS +SPICE_IS_PORT_CHANNEL_CLASS +SPICE_PORT_CHANNEL_GET_CLASS + +SpicePortChannelPrivate +
+ +
+spice-uri +spice_uri_get_scheme +spice_uri_set_scheme +spice_uri_get_hostname +spice_uri_set_hostname +spice_uri_get_port +spice_uri_set_port +spice_uri_get_user +spice_uri_set_user +spice_uri_get_password +spice_uri_set_password +spice_uri_to_string +SpiceURIClass +SpiceURI + +SPICE_IS_URI +SPICE_IS_URI_CLASS +SPICE_TYPE_URI +SPICE_URI +SPICE_URI_CLASS +SPICE_URI_GET_CLASS +spice_uri_get_type + +SpiceURIPrivate +
+ +
+channel-webdav +SpiceWebdavChannel +SpiceWebdavChannel +SpiceWebdavChannelClass + +SPICE_IS_WEBDAV_CHANNEL +SPICE_IS_WEBDAV_CHANNEL_CLASS +SPICE_TYPE_WEBDAV_CHANNEL +SPICE_WEBDAV_CHANNEL +SPICE_WEBDAV_CHANNEL_CLASS +SPICE_WEBDAV_CHANNEL_GET_CLASS +spice_webdav_channel_get_type + +SpiceWebdavChannelPrivate +
+ +
+file-transfer-task +SpiceFileTransferTask + +spice_file_transfer_task_get_progress +spice_file_transfer_task_get_filename +spice_file_transfer_task_cancel + +SPICE_FILE_TRANSFER_TASK +SPICE_IS_FILE_TRANSFER_TASK +SPICE_TYPE_FILE_TRANSFER_TASK +spice_file_transfer_task_get_type +SPICE_FILE_TRANSFER_TASK_CLASS +SPICE_IS_FILE_TRANSFER_TASK_CLASS +SPICE_FILE_TRANSFER_TASK_GET_CLASS + +SpiceFileTransferTask +SpiceFileTransferTaskClass +SpiceFileTransferTaskPrivate +
diff --git a/doc/reference/spice-gtk.types b/doc/reference/spice-gtk.types new file mode 100644 index 0000000..e14ae1b --- /dev/null +++ b/doc/reference/spice-gtk.types @@ -0,0 +1,49 @@ +#include "spice-audio.h" +#include "spice-client.h" +#include "spice-types.h" +#include "spice-session.h" +#include "spice-channel.h" +#include "spice-glib-enums.h" +#include "spice-util.h" +#include "channel-main.h" +#include "channel-display.h" +#include "channel-cursor.h" +#include "channel-inputs.h" +#include "channel-playback.h" +#include "channel-record.h" +#include "channel-smartcard.h" +#include "channel-usbredir.h" +#include "channel-webdav.h" +#include "spice-gtk-session.h" +#include "spice-widget.h" +#include "spice-grabsequence.h" +#include "smartcard-manager.h" +#include "usb-device-manager.h" +#include "usb-device-widget.h" +#include "spice-file-transfer-task.h" + +spice_audio_get_type +spice_channel_event_get_type +spice_channel_get_type +spice_cursor_channel_get_type +spice_display_channel_get_type +spice_display_get_type +spice_grab_sequence_get_type +spice_gtk_session_get_type +spice_inputs_channel_get_type +spice_inputs_lock_get_type +spice_main_channel_get_type +spice_playback_channel_get_type +spice_record_channel_get_type +spice_session_get_type +spice_session_verify_get_type +spice_smartcard_channel_get_type +spice_smartcard_manager_get_type +spice_session_verify_get_type +spice_usbredir_channel_get_type +spice_usb_device_get_type +spice_usb_device_manager_get_type +spice_usb_device_widget_get_type +spice_port_channel_get_type +spice_webdav_channel_get_type +spice_file_transfer_task_get_type diff --git a/gtk-doc.make b/gtk-doc.make new file mode 100644 index 0000000..e4a12a5 --- /dev/null +++ b/gtk-doc.make @@ -0,0 +1,304 @@ +# -*- mode: makefile -*- + +#################################### +# Everything below here is generic # +#################################### + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = +endif + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) + +SETUP_FILES = \ + $(content_files) \ + $(expand_content_files) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt + +EXTRA_DIST = \ + $(HTML_IMAGES) \ + $(SETUP_FILES) + +DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \ + html-build.stamp pdf-build.stamp \ + sgml.stamp html.stamp pdf.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +gtkdoc-check.test: Makefile + $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ + echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ + chmod +x $@ + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test + +if GTK_DOC_BUILD_HTML +HTML_BUILD_STAMP=html-build.stamp +else +HTML_BUILD_STAMP= +endif +if GTK_DOC_BUILD_PDF +PDF_BUILD_STAMP=pdf-build.stamp +else +PDF_BUILD_STAMP= +endif + +all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) +.PHONY: all-gtk-doc + +if ENABLE_GTK_DOC +all-local: all-gtk-doc +endif + +docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) + +$(REPORT_FILES): sgml-build.stamp + +#### setup #### + +GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_$(V)) +GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SETUP_0=@echo " DOC Preparing build"; + +setup-build.stamp: + -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ + if test "x$$files" != "x" ; then \ + for file in $$files ; do \ + destdir=`dirname $(abs_builddir)/$$file`; \ + test -d "$$destdir" || mkdir -p "$$destdir"; \ + test -f $(abs_srcdir)/$$file && \ + cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ + done; \ + fi; \ + fi + $(AM_V_at)touch setup-build.stamp + + +#### scan #### + +GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_$(V)) +GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files"; + +GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_$(V)) +GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects"; + +scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) + $(GTK_DOC_V_SCAN)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) + $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ + scanobj_options=""; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + scanobj_options="--verbose"; \ + fi; \ + fi; \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + $(AM_V_at)touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +GTK_DOC_V_XML=$(GTK_DOC_V_XML_$(V)) +GTK_DOC_V_XML_=$(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XML_0=@echo " DOC Building XML"; + +sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent + $(GTK_DOC_V_XML)_source_dir='' ; \ + for i in $(DOC_SOURCE_DIR) ; do \ + _source_dir="$${_source_dir} --source-dir=$$i" ; \ + done ; \ + gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) + $(AM_V_at)touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +xml/gtkdocentities.ent: Makefile + $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + echo ""; \ + ) > $@ + +#### html #### + +GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_$(V)) +GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_HTML_0=@echo " DOC Building HTML"; + +GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_$(V)) +GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references"; + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkhtml_options="$$mkhtml_options --verbose"; \ + fi; \ + fi; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$$?" = "0"; then \ + mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + -@test "x$(HTML_IMAGES)" = "x" || \ + for file in $(HTML_IMAGES) ; do \ + if test -f $(abs_srcdir)/$$file ; then \ + cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ + fi; \ + if test -f $(abs_builddir)/$$file ; then \ + cp $(abs_builddir)/$$file $(abs_builddir)/html; \ + fi; \ + done; + $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + $(AM_V_at)touch html-build.stamp + +#### pdf #### + +GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_$(V)) +GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) +GTK_DOC_V_PDF_0=@echo " DOC Building PDF"; + +pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) + $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ + mkpdf_options=""; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + if test "$$?" = "0"; then \ + if test "x$(V)" = "x1"; then \ + mkpdf_options="$$mkpdf_options --verbose"; \ + fi; \ + fi; \ + if test "x$(HTML_IMAGES)" != "x"; then \ + for img in $(HTML_IMAGES); do \ + part=`dirname $$img`; \ + echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + if test $$? != 0; then \ + mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ + fi; \ + done; \ + fi; \ + gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) + $(AM_V_at)touch pdf-build.stamp + +############## + +clean-local: + @rm -f *~ *.bak + @rm -rf .libs + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + rm -f $(DOC_MODULE).types; \ + fi + @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + rm -f $(DOC_MODULE)-sections.txt; \ + fi + +distclean-local: + @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ + fi + +maintainer-clean-local: + @rm -rf xml html + +install-data-local: + @installfiles=`echo $(builddir)/html/*`; \ + if test "$$installfiles" = '$(builddir)/html/*'; \ + then echo 1>&2 'Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo ' $(INSTALL_DATA) '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + fi; \ + $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ + fi + +uninstall-local: + @if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +if HAVE_GTK_DOC +dist-check-gtkdoc: docs +else +dist-check-gtkdoc: + @echo "*** gtk-doc is needed to run 'make dist'. ***" + @echo "*** gtk-doc was not found when 'configure' ran. ***" + @echo "*** please install gtk-doc and rerun 'configure'. ***" + @false +endif + +dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local + @mkdir $(distdir)/html + @cp ./html/* $(distdir)/html + @-cp ./$(DOC_MODULE).pdf $(distdir)/ + @-cp ./$(DOC_MODULE).types $(distdir)/ + @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ + @cd $(distdir) && rm -f $(DISTCLEANFILES) + @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs diff --git a/intltool-extract.in b/intltool-extract.in new file mode 100644 index 0000000..e69de29 diff --git a/intltool-merge.in b/intltool-merge.in new file mode 100644 index 0000000..e69de29 diff --git a/intltool-update.in b/intltool-update.in new file mode 100644 index 0000000..e69de29 diff --git a/m4/gtk-doc.m4 b/m4/gtk-doc.m4 new file mode 100644 index 0000000..3675543 --- /dev/null +++ b/m4/gtk-doc.m4 @@ -0,0 +1,88 @@ +dnl -*- mode: autoconf -*- + +# serial 2 + +dnl Usage: +dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) +AC_DEFUN([GTK_DOC_CHECK], +[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + + ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"]) + AC_MSG_CHECKING([for gtk-doc]) + PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no]) + AC_MSG_RESULT($have_gtk_doc) + + if test "$have_gtk_doc" = "no"; then + AC_MSG_WARN([ + You will not be able to create source packages with 'make dist' + because $gtk_doc_requires is not found.]) + fi + + dnl check for tools we added during development + dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that + dnl may not be writable by the user. Currently, automake requires that the + dnl test name must end in '.test'. + dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638 + AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test]) + AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check]) + AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) + AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) + + dnl for overriding the documentation installation directory + AC_ARG_WITH([html-dir], + AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, + [with_html_dir='${datadir}/gtk-doc/html']) + HTML_DIR="$with_html_dir" + AC_SUBST([HTML_DIR]) + + dnl enable/disable documentation building + AC_ARG_ENABLE([gtk-doc], + AS_HELP_STRING([--enable-gtk-doc], + [use gtk-doc to build documentation [[default=no]]]),, + [enable_gtk_doc=no]) + + AC_MSG_CHECKING([whether to build gtk-doc documentation]) + AC_MSG_RESULT($enable_gtk_doc) + + if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then + AC_MSG_ERROR([ + You must have $gtk_doc_requires installed to build documentation for + $PACKAGE_NAME. Please install gtk-doc or disable building the + documentation by adding '--disable-gtk-doc' to '[$]0'.]) + fi + + dnl don't check for glib if we build glib + if test "x$PACKAGE_NAME" != "xglib"; then + dnl don't fail if someone does not have glib + PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) + fi + + dnl enable/disable output formats + AC_ARG_ENABLE([gtk-doc-html], + AS_HELP_STRING([--enable-gtk-doc-html], + [build documentation in html format [[default=yes]]]),, + [enable_gtk_doc_html=yes]) + AC_ARG_ENABLE([gtk-doc-pdf], + AS_HELP_STRING([--enable-gtk-doc-pdf], + [build documentation in pdf format [[default=no]]]),, + [enable_gtk_doc_pdf=no]) + + if test -z "$GTKDOC_MKPDF"; then + enable_gtk_doc_pdf=no + fi + + if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 + fi + AC_SUBST([AM_DEFAULT_VERBOSITY]) + + AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes]) + AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) + AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) + AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) + AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) +]) diff --git a/m4/intltool.m4 b/m4/intltool.m4 new file mode 100644 index 0000000..c25b7b1 --- /dev/null +++ b/m4/intltool.m4 @@ -0,0 +1,212 @@ +## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*- +## Copyright (C) 2001 Eazel, Inc. +## Author: Maciej Stachowiak +## Kenneth Christiansen +## +## 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. + +dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) +# serial 42 IT_PROG_INTLTOOL +AC_DEFUN([IT_PROG_INTLTOOL], [ +AC_PREREQ([2.50])dnl +AC_REQUIRE([AM_NLS])dnl + +case "$am__api_version" in + 1.[01234]) + AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool]) + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n "$1"; then + AC_MSG_CHECKING([for intltool >= $1]) + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.]) +fi + +AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update]) +AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge]) +AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract]) +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi +AC_SUBST([AM_DEFAULT_VERBOSITY]) + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " [$]@;' +AC_SUBST(INTLTOOL_V_MERGE) +AC_SUBST(INTLTOOL__v_MERGE_) +AC_SUBST(INTLTOOL__v_MERGE_0) + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' +AC_SUBST(INTLTOOL_V_MERGE_OPTIONS) +AC_SUBST(intltool__v_merge_options_) +AC_SUBST(intltool__v_merge_options_0) + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< [$]@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< [$]@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.[$][$]RANDOM && mkdir [$][$]_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u [$][$]_it_tmp_dir $< [$]@ && rmdir [$][$]_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + +_IT_SUBST(INTLTOOL_DESKTOP_RULE) +_IT_SUBST(INTLTOOL_DIRECTORY_RULE) +_IT_SUBST(INTLTOOL_KEYS_RULE) +_IT_SUBST(INTLTOOL_PROP_RULE) +_IT_SUBST(INTLTOOL_OAF_RULE) +_IT_SUBST(INTLTOOL_PONG_RULE) +_IT_SUBST(INTLTOOL_SERVER_RULE) +_IT_SUBST(INTLTOOL_SHEET_RULE) +_IT_SUBST(INTLTOOL_SOUNDLIST_RULE) +_IT_SUBST(INTLTOOL_UI_RULE) +_IT_SUBST(INTLTOOL_XAM_RULE) +_IT_SUBST(INTLTOOL_KBD_RULE) +_IT_SUBST(INTLTOOL_XML_RULE) +_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE) +_IT_SUBST(INTLTOOL_CAVES_RULE) +_IT_SUBST(INTLTOOL_SCHEMAS_RULE) +_IT_SUBST(INTLTOOL_THEME_RULE) +_IT_SUBST(INTLTOOL_SERVICE_RULE) +_IT_SUBST(INTLTOOL_POLICY_RULE) + +# Check the gettext tools to make sure they are GNU +AC_PATH_PROG(XGETTEXT, xgettext) +AC_PATH_PROG(MSGMERGE, msgmerge) +AC_PATH_PROG(MSGFMT, msgfmt) +AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi + +AC_PATH_PROG(INTLTOOL_PERL, perl) +if test -z "$INTLTOOL_PERL"; then + AC_MSG_ERROR([perl not found]) +fi +AC_MSG_CHECKING([for perl >= 5.8.1]) +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_ERROR([perl 5.8.1 is required for intltool]) +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + AC_MSG_RESULT([$IT_PERL_VERSION]) +fi +if test "x$2" != "xno-xml"; then + AC_MSG_CHECKING([for XML::Parser]) + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + AC_MSG_RESULT([ok]) + else + AC_MSG_ERROR([XML::Parser perl module is required for intltool]) + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile +AC_SUBST(ALL_LINGUAS) + +IT_PO_SUBDIR([po]) + +]) + + +# IT_PO_SUBDIR(DIRNAME) +# --------------------- +# All po subdirs have to be declared with this macro; the subdir "po" is +# declared by IT_PROG_INTLTOOL. +# +AC_DEFUN([IT_PO_SUBDIR], +[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS. +dnl +dnl The following CONFIG_COMMANDS should be executed at the very end +dnl of config.status. +AC_CONFIG_COMMANDS_PRE([ + AC_CONFIG_COMMANDS([$1/stamp-it], [ + if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then + AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.]) + fi + rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp" + >"$1/stamp-it.tmp" + [sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES" + ] + [sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r $1/POTFILES + } + ' "$1/Makefile.in" >"$1/Makefile"] + rm -f "$1/Makefile.tmp" + mv "$1/stamp-it.tmp" "$1/stamp-it" + ]) +])dnl +]) + +# _IT_SUBST(VARIABLE) +# ------------------- +# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +# +AC_DEFUN([_IT_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + +# deprecated macros +AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL]) +# A hint is needed for aclocal from Automake <= 1.9.4: +# AC_DEFUN([AC_PROG_INTLTOOL], ...) + diff --git a/m4/ld-version.m4 b/m4/ld-version.m4 new file mode 100644 index 0000000..589fb71 --- /dev/null +++ b/m4/ld-version.m4 @@ -0,0 +1,34 @@ +dnl Check whether the linker supports --version-script. +dnl +dnl Probes whether the linker supports --version-script with a simple version +dnl script that only defines a single version. Sets the Automake conditional +dnl HAVE_LD_VERSION_SCRIPT based on whether it is supported. +dnl +dnl Written by Russ Allbery +dnl Based on the gnulib ld-version-script macro from Simon Josefsson +dnl Copyright 2010 Board of Trustees, Leland Stanford Jr. University +dnl Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +dnl +dnl This file is free software; the Free Software Foundation gives unlimited +dnl permission to copy and/or distribute it, with or without modifications, as +dnl long as this notice is preserved. + +AC_DEFUN([RRA_LD_VERSION_SCRIPT], +[AC_CACHE_CHECK([if -Wl,--version-script works], [rra_cv_ld_version_script], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + cat > conftest.map <. +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4 new file mode 100644 index 0000000..90823b0 --- /dev/null +++ b/m4/manywarnings.m4 @@ -0,0 +1,274 @@ +# manywarnings.m4 serial 8 +dnl Copyright (C) 2008-2016 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 Simon Josefsson + +# gl_MANYWARN_COMPLEMENT(OUTVAR, LISTVAR, REMOVEVAR) +# -------------------------------------------------- +# Copy LISTVAR to OUTVAR except for the entries in REMOVEVAR. +# Elements separated by whitespace. In set logic terms, the function +# does OUTVAR = LISTVAR \ REMOVEVAR. +AC_DEFUN([gl_MANYWARN_COMPLEMENT], +[ + gl_warn_set= + set x $2; shift + for gl_warn_item + do + case " $3 " in + *" $gl_warn_item "*) + ;; + *) + gl_warn_set="$gl_warn_set $gl_warn_item" + ;; + esac + done + $1=$gl_warn_set +]) + +# gl_MANYWARN_ALL_GCC(VARIABLE) +# ----------------------------- +# Add all documented GCC warning parameters to variable VARIABLE. +# Note that you need to test them using gl_WARN_ADD if you want to +# make sure your gcc understands it. +AC_DEFUN([gl_MANYWARN_ALL_GCC], +[ + dnl First, check for some issues that only occur when combining multiple + dnl gcc warning categories. + AC_REQUIRE([AC_PROG_CC]) + if test -n "$GCC"; then + + dnl Check if -W -Werror -Wno-missing-field-initializers is supported + dnl with the current $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether -Wno-missing-field-initializers is supported]) + AC_CACHE_VAL([gl_cv_cc_nomfi_supported], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror -Wno-missing-field-initializers" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_nomfi_supported=yes], + [gl_cv_cc_nomfi_supported=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_nomfi_supported]) + + if test "$gl_cv_cc_nomfi_supported" = yes; then + dnl Now check whether -Wno-missing-field-initializers is needed + dnl for the { 0, } construct. + AC_MSG_CHECKING([whether -Wno-missing-field-initializers is needed]) + AC_CACHE_VAL([gl_cv_cc_nomfi_needed], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -W -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[void f (void) + { + typedef struct { int a; int b; } s_t; + s_t s1 = { 0, }; + } + ]], + [[]])], + [gl_cv_cc_nomfi_needed=no], + [gl_cv_cc_nomfi_needed=yes]) + CFLAGS="$gl_save_CFLAGS" + ]) + AC_MSG_RESULT([$gl_cv_cc_nomfi_needed]) + fi + + dnl Next, check if -Werror -Wuninitialized is useful with the + dnl user's choice of $CFLAGS; some versions of gcc warn that it + dnl has no effect if -O is not also used + AC_MSG_CHECKING([whether -Wuninitialized is supported]) + AC_CACHE_VAL([gl_cv_cc_uninitialized_supported], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror -Wuninitialized" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_uninitialized_supported=yes], + [gl_cv_cc_uninitialized_supported=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_uninitialized_supported]) + + fi + + # List all gcc warning categories. + # To compare this list to your installed GCC's, run this Bash command: + # + # comm -3 \ + # <(sed -n 's/^ *\(-[^ ]*\) .*/\1/p' manywarnings.m4 | sort) \ + # <(gcc --help=warnings | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort | + # grep -v -x -f <( + # awk '/^[^#]/ {print $1}' ../build-aux/gcc-warning.spec)) + + gl_manywarn_set= + for gl_manywarn_item in \ + -W \ + -Wabi \ + -Waddress \ + -Waggressive-loop-optimizations \ + -Wall \ + -Wattributes \ + -Wbad-function-cast \ + -Wbool-compare \ + -Wbuiltin-macro-redefined \ + -Wcast-align \ + -Wchar-subscripts \ + -Wchkp \ + -Wclobbered \ + -Wcomment \ + -Wcomments \ + -Wcoverage-mismatch \ + -Wcpp \ + -Wdate-time \ + -Wdeprecated \ + -Wdeprecated-declarations \ + -Wdesignated-init \ + -Wdisabled-optimization \ + -Wdiscarded-array-qualifiers \ + -Wdiscarded-qualifiers \ + -Wdiv-by-zero \ + -Wdouble-promotion \ + -Wduplicated-cond \ + -Wempty-body \ + -Wendif-labels \ + -Wenum-compare \ + -Wextra \ + -Wformat-contains-nul \ + -Wformat-extra-args \ + -Wformat-nonliteral \ + -Wformat-security \ + -Wformat-signedness \ + -Wformat-y2k \ + -Wformat-zero-length \ + -Wframe-address \ + -Wfree-nonheap-object \ + -Whsa \ + -Wignored-attributes \ + -Wignored-qualifiers \ + -Wimplicit \ + -Wimplicit-function-declaration \ + -Wimplicit-int \ + -Wincompatible-pointer-types \ + -Winit-self \ + -Winline \ + -Wint-conversion \ + -Wint-to-pointer-cast \ + -Winvalid-memory-model \ + -Winvalid-pch \ + -Wjump-misses-init \ + -Wlogical-not-parentheses \ + -Wlogical-op \ + -Wmain \ + -Wmaybe-uninitialized \ + -Wmemset-transposed-args \ + -Wmisleading-indentation \ + -Wmissing-braces \ + -Wmissing-declarations \ + -Wmissing-field-initializers \ + -Wmissing-include-dirs \ + -Wmissing-parameter-type \ + -Wmissing-prototypes \ + -Wmultichar \ + -Wnarrowing \ + -Wnested-externs \ + -Wnonnull \ + -Wnonnull-compare \ + -Wnull-dereference \ + -Wodr \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wopenmp-simd \ + -Woverflow \ + -Woverlength-strings \ + -Woverride-init \ + -Wpacked \ + -Wpacked-bitfield-compat \ + -Wparentheses \ + -Wpointer-arith \ + -Wpointer-sign \ + -Wpointer-to-int-cast \ + -Wpragmas \ + -Wreturn-local-addr \ + -Wreturn-type \ + -Wscalar-storage-order \ + -Wsequence-point \ + -Wshadow \ + -Wshift-count-negative \ + -Wshift-count-overflow \ + -Wshift-negative-value \ + -Wsizeof-array-argument \ + -Wsizeof-pointer-memaccess \ + -Wstack-protector \ + -Wstrict-aliasing \ + -Wstrict-overflow \ + -Wstrict-prototypes \ + -Wsuggest-attribute=const \ + -Wsuggest-attribute=format \ + -Wsuggest-attribute=noreturn \ + -Wsuggest-attribute=pure \ + -Wsuggest-final-methods \ + -Wsuggest-final-types \ + -Wswitch \ + -Wswitch-bool \ + -Wswitch-default \ + -Wsync-nand \ + -Wsystem-headers \ + -Wtautological-compare \ + -Wtrampolines \ + -Wtrigraphs \ + -Wtype-limits \ + -Wuninitialized \ + -Wunknown-pragmas \ + -Wunsafe-loop-optimizations \ + -Wunused \ + -Wunused-but-set-parameter \ + -Wunused-but-set-variable \ + -Wunused-function \ + -Wunused-label \ + -Wunused-local-typedefs \ + -Wunused-macros \ + -Wunused-parameter \ + -Wunused-result \ + -Wunused-value \ + -Wunused-variable \ + -Wvarargs \ + -Wvariadic-macros \ + -Wvector-operation-performance \ + -Wvla \ + -Wvolatile-register-var \ + -Wwrite-strings \ + \ + ; do + gl_manywarn_set="$gl_manywarn_set $gl_manywarn_item" + done + + # gcc --help=warnings outputs an unusual form for these options; list + # them here so that the above 'comm' command doesn't report a false match. + gl_manywarn_set="$gl_manywarn_set -Warray-bounds=2" + gl_manywarn_set="$gl_manywarn_set -Wnormalized=nfc" + gl_manywarn_set="$gl_manywarn_set -Wshift-overflow=2" + gl_manywarn_set="$gl_manywarn_set -Wunused-const-variable=2" + + # These are needed for older GCC versions. + if test -n "$GCC"; then + case `($CC --version) 2>/dev/null` in + 'gcc (GCC) '[[0-3]].* | \ + 'gcc (GCC) '4.[[0-7]].*) + gl_manywarn_set="$gl_manywarn_set -fdiagnostics-show-option" + gl_manywarn_set="$gl_manywarn_set -funit-at-a-time" + ;; + esac + fi + + # Disable specific options as needed. + if test "$gl_cv_cc_nomfi_needed" = yes; then + gl_manywarn_set="$gl_manywarn_set -Wno-missing-field-initializers" + fi + + if test "$gl_cv_cc_uninitialized_supported" = no; then + gl_manywarn_set="$gl_manywarn_set -Wno-uninitialized" + fi + + $1=$gl_manywarn_set +]) diff --git a/m4/spice-compile-warnings.m4 b/m4/spice-compile-warnings.m4 new file mode 100644 index 0000000..533bac6 --- /dev/null +++ b/m4/spice-compile-warnings.m4 @@ -0,0 +1,150 @@ +# SPICE_COMPILE_WARNINGS(DONTWARN) +# -------------------------------------------------------- +# Enable all known GCC compiler warnings, except for those +# we can't yet cope with +# +AC_DEFUN([SPICE_COMPILE_WARNINGS],[ + dnl ****************************** + dnl More compiler warnings + dnl ****************************** + + AC_ARG_ENABLE([werror], + AS_HELP_STRING([--enable-werror], [Use -Werror (if supported)]), + [set_werror="$enableval"], + [if test -d $srcdir/.git; then + is_git_version=true + set_werror=yes + else + set_werror=no + fi]) + + # List of warnings that are not relevant / wanted + + dontwarn=$1 + + # Don't care about C++ compiler compat + dontwarn="$dontwarn -Wc++-compat" + dontwarn="$dontwarn -Wabi" + dontwarn="$dontwarn -Wdeprecated" + # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional" + # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional-conversion" + # Ignore warnings in /usr/include + dontwarn="$dontwarn -Wsystem-headers" + # Happy for compiler to add struct padding + dontwarn="$dontwarn -Wpadded" + # GCC very confused with -O2 + dontwarn="$dontwarn -Wunreachable-code" + + + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wvla" + dontwarn="$dontwarn -Wundef" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wlong-long" + dontwarn="$dontwarn -Wswitch-default" + dontwarn="$dontwarn -Wswitch-enum" + dontwarn="$dontwarn -Wstrict-overflow" + dontwarn="$dontwarn -Wunsafe-loop-optimizations" + dontwarn="$dontwarn -Wformat-nonliteral" + dontwarn="$dontwarn -Wfloat-equal" + dontwarn="$dontwarn -Wdeclaration-after-statement" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wpacked" + dontwarn="$dontwarn -Wunused-macros" + dontwarn="$dontwarn -Woverlength-strings" + dontwarn="$dontwarn -Wstack-protector" + dontwarn="$dontwarn -Winline" + dontwarn="$dontwarn -Wbad-function-cast" + dontwarn="$dontwarn -Wshadow" + + # Get all possible GCC warnings + gl_MANYWARN_ALL_GCC([maybewarn]) + + # Remove the ones we don't want, blacklisted earlier + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) + + # Check for $CC support of each warning + for w in $wantwarn; do + gl_WARN_ADD([$w]) + done + + # GNULIB uses '-W' (aka -Wextra) which includes a bunch of stuff. + # Unfortunately, this means you can't simply use '-Wsign-compare' + # with gl_MANYWARN_COMPLEMENT + # So we have -W enabled, and then have to explicitly turn off... + gl_WARN_ADD([-Wno-sign-compare]) + gl_WARN_ADD([-Wno-unused-parameter]) + gl_WARN_ADD([-Wno-missing-field-initializers]) + # We can't enable this due to horrible spice_usb_device_get_description + # signature + gl_WARN_ADD([-Wno-format-nonliteral]) + # We use some deprecated functions to avoid #ifdef hell while maintaining + # compat with older gtk / glib versions + gl_WARN_ADD([-Wno-deprecated-declarations]) + + + + # GNULIB expects this to be part of -Wc++-compat, but we turn + # that one off, so we need to manually enable this again + gl_WARN_ADD([-Wjump-misses-init]) + + # GNULIB turns on -Wformat=2 which implies -Wformat-nonliteral, + # so we need to manually re-exclude it. + gl_WARN_ADD([-Wno-format-nonliteral]) + + # This should be < 1024 really. pixman_utils is the blackspot + # preventing lower usage + gl_WARN_ADD([-Wframe-larger-than=9216]) + + # Use improved glibc headers + AH_VERBATIM([FORTIFY_SOURCE], + [/* Enable compile-time and run-time bounds-checking, and some warnings. */ + #if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ + # define _FORTIFY_SOURCE 2 + #endif + ]) + + # Extra special flags + dnl -fstack-protector stuff passes gl_WARN_ADD with gcc + dnl on Mingw32, but fails when actually used + case $host in + *-*-linux*) + dnl Fedora only uses -fstack-protector, but doesn't seem to + dnl be great overhead in adding -fstack-protector-all instead + dnl gl_WARN_ADD([-fstack-protector]) + gl_WARN_ADD([-fstack-protector-all]) + gl_WARN_ADD([--param=ssp-buffer-size=4]) + ;; + esac + gl_WARN_ADD([-fexceptions]) + gl_WARN_ADD([-fasynchronous-unwind-tables]) + gl_WARN_ADD([-fdiagnostics-show-option]) + gl_WARN_ADD([-funit-at-a-time]) + + # Need -fipa-pure-const in order to make -Wsuggest-attribute=pure + # fire even without -O. + gl_WARN_ADD([-fipa-pure-const]) + + # We should eventually enable this, but right now there are at + # least 75 functions triggering warnings. + gl_WARN_ADD([-Wno-suggest-attribute=pure]) + gl_WARN_ADD([-Wno-suggest-attribute=const]) + + if test "$set_werror" = "yes" + then + gl_WARN_ADD([-Werror]) + fi + + WARN_LDFLAGS=$WARN_CFLAGS + AC_SUBST([WARN_CFLAGS]) + AC_SUBST([WARN_LDFLAGS]) + + gl_WARN_ADD([-Wno-write-strings]) + WARN_PYFLAGS=$WARN_CFLAGS + AC_SUBST([WARN_PYFLAGS]) +]) diff --git a/m4/warnings.m4 b/m4/warnings.m4 new file mode 100644 index 0000000..e3d239b --- /dev/null +++ b/m4/warnings.m4 @@ -0,0 +1,79 @@ +# warnings.m4 serial 11 +dnl Copyright (C) 2008-2013 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 Simon Josefsson + +# gl_AS_VAR_APPEND(VAR, VALUE) +# ---------------------------- +# Provide the functionality of AS_VAR_APPEND if Autoconf does not have it. +m4_ifdef([AS_VAR_APPEND], +[m4_copy([AS_VAR_APPEND], [gl_AS_VAR_APPEND])], +[m4_define([gl_AS_VAR_APPEND], +[AS_VAR_SET([$1], [AS_VAR_GET([$1])$2])])]) + + +# gl_COMPILER_OPTION_IF(OPTION, [IF-SUPPORTED], [IF-NOT-SUPPORTED], +# [PROGRAM = AC_LANG_PROGRAM()]) +# ----------------------------------------------------------------- +# Check if the compiler supports OPTION when compiling PROGRAM. +# +# FIXME: gl_Warn must be used unquoted until we can assume Autoconf +# 2.64 or newer. +AC_DEFUN([gl_COMPILER_OPTION_IF], +[AS_VAR_PUSHDEF([gl_Warn], [gl_cv_warn_[]_AC_LANG_ABBREV[]_$1])dnl +AS_VAR_PUSHDEF([gl_Flags], [_AC_LANG_PREFIX[]FLAGS])dnl +AS_LITERAL_IF([$1], + [m4_pushdef([gl_Positive], m4_bpatsubst([$1], [^-Wno-], [-W]))], + [gl_positive="$1" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +m4_pushdef([gl_Positive], [$gl_positive])])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler handles $1], m4_defn([gl_Warn]), [ + gl_save_compiler_FLAGS="$gl_Flags" + gl_AS_VAR_APPEND(m4_defn([gl_Flags]), + [" $gl_unknown_warnings_are_errors ]m4_defn([gl_Positive])["]) + AC_LINK_IFELSE([m4_default([$4], [AC_LANG_PROGRAM([])])], + [AS_VAR_SET(gl_Warn, [yes])], + [AS_VAR_SET(gl_Warn, [no])]) + gl_Flags="$gl_save_compiler_FLAGS" +]) +AS_VAR_IF(gl_Warn, [yes], [$2], [$3]) +m4_popdef([gl_Positive])dnl +AS_VAR_POPDEF([gl_Flags])dnl +AS_VAR_POPDEF([gl_Warn])dnl +]) + +# gl_UNKNOWN_WARNINGS_ARE_ERRORS +# ------------------------------ +# Clang doesn't complain about unknown warning options unless one also +# specifies -Wunknown-warning-option -Werror. Detect this. +AC_DEFUN([gl_UNKNOWN_WARNINGS_ARE_ERRORS], +[gl_COMPILER_OPTION_IF([-Werror -Wunknown-warning-option], + [gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror'], + [gl_unknown_warnings_are_errors=])]) + +# gl_WARN_ADD(OPTION, [VARIABLE = WARN_CFLAGS], +# [PROGRAM = AC_LANG_PROGRAM()]) +# --------------------------------------------- +# Adds parameter to WARN_CFLAGS if the compiler supports it when +# compiling PROGRAM. For example, gl_WARN_ADD([-Wparentheses]). +# +# If VARIABLE is a variable name, AC_SUBST it. +AC_DEFUN([gl_WARN_ADD], +[AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) +gl_COMPILER_OPTION_IF([$1], + [gl_AS_VAR_APPEND(m4_if([$2], [], [[WARN_CFLAGS]], [[$2]]), [" $1"])], + [], + [$3]) +m4_ifval([$2], + [AS_LITERAL_IF([$2], [AC_SUBST([$2])])], + [AC_SUBST([WARN_CFLAGS])])dnl +]) + +# Local Variables: +# mode: autoconf +# End: diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..a8f7e3f --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,16 @@ +NULL = + +dist_man_MANS = \ + spice-client.1 \ + $(NULL) + +EXTRA_DIST = \ + spice-client.pod \ + $(NULL) + +MAINTAINERCLEANFILES = $(dist_man_MANS) + +%.1: %.pod + $(AM_V_GEN)pod2man -c "Spice-GTK Documentation" $< > $@ + +-include $(top_srcdir)/git.mk diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 0000000..a2d5413 --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" +NROFF = nroff +MANS = $(dist_man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +dist_man_MANS = \ + spice-client.1 \ + $(NULL) + +EXTRA_DIST = \ + spice-client.pod \ + $(NULL) + +MAINTAINERCLEANFILES = $(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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +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-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-man \ + uninstall-man1 + +.PRECIOUS: Makefile + + +%.1: %.pod + $(AM_V_GEN)pod2man -c "Spice-GTK Documentation" $< > $@ + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/spice-client.1 b/man/spice-client.1 new file mode 100644 index 0000000..129fc20 --- /dev/null +++ b/man/spice-client.1 @@ -0,0 +1,301 @@ +.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "SPICE-CLIENT 1" +.TH SPICE-CLIENT 1 "2015-11-10" "perl v5.22.2" "Spice-GTK Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Spice\-GTK \- a client\-side library to access remote SPICE displays +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Spice-GTK is a library allowing access to remote displays over the \s-1SPICE\s0 +protocol. At the moment It's mainly used to access remote virtual machines. +.PP +The Spice-GTK library provides a set of command line options which +can be used to tweak some SPICE-specific option. +.SH "URI" +.IX Header "URI" +The most basic \s-1SPICE URI\s0 which can be used is in the form + spice://hostname.example.com:5900 +.PP +This will try to initiate a \s-1SPICE\s0 connection to hostname.example.com +to port 5900. This connection will be unencrypted. This \s-1URI\s0 is +equivalent to + spice://hostname.example.com?port=5900 +.PP +In order to start a \s-1TLS\s0 connection, one would use + spice://hostname.example.com?tls\-port=5900 +.PP +Other valid \s-1URI\s0 parameters are 'username' and 'password'. Be careful that +passing a password through a \s-1SPICE URI\s0 might cause the password to be +visible by any local user through 'ps'. +.PP +Several parameters can be specified at once if they are separated +by & or ; + spice://hostname.example.com?port=5900;tls\-port=5901 +.PP +When using 'tls\-port', it's recommended to not specify any non-TLS port. +If you give both 'port' and 'tls\-port', make sure you use the +\&\-\-spice\-secure\-channels options to indicate which channels must be secure. +Otherwise, Spice-GTK first attempts a connection to the non-TLS port, and +then try to use the \s-1TLS\s0 port. This means a man-in-the-middle could force +the whole \s-1SPICE\s0 session to go in clear text regardless of the \s-1TLS\s0 settings +of the \s-1SPICE\s0 server. +.SH "OPTIONS" +.IX Header "OPTIONS" +The following options are accepted when running a \s-1SPICE\s0 client which +makes use of the default Spice-GTK options: +.IP "\-\-spice\-secure\-channels=" 4 +.IX Item "--spice-secure-channels=" +Force the specified channels to be secured +.Sp +This instructs the \s-1SPICE\s0 client that it must use a \s-1TLS\s0 connection for these +channels. If the server only offers non-TLS connections for these channels, +the client will not use these. If the special value \*(L"all\*(R" is used, this +indicates that all \s-1SPICE\s0 channels must be encrypted. +.Sp +The current \s-1SPICE\s0 channels are: main, display, inputs, cursor, playback, +record, smartcard, usbredir. +.IP "\-\-spice\-disable\-effects=" 4 +.IX Item "--spice-disable-effects=" +Disable guest display effects +.Sp +This tells the \s-1SPICE\s0 client that it should attempt to disable some guest +features in order to lower bandwidth usage. This requires guest support, +usually through a \s-1SPICE\s0 agent. This is currently only supported on Windows +guests. +.Sp +\&\*(L"wallpaper\*(R" will disable the guest wallpaper, \*(L"font-smooth\*(R" will disable +font antialiasing, \*(L"animation\*(R" will try to disable some of the desktop +environment animations. \*(L"all\*(R" will attempt to disable everything which +can be disabled. +.IP "\-\-spice\-color\-depth=<16,32>" 4 +.IX Item "--spice-color-depth=<16,32>" +Guest display color depth +.Sp +This tells the \s-1SPICE\s0 client that it should attempt to force the guest \s-1OS\s0 +color depth. A lower color depth should lower bandwith usage. This requires +guest support, usually through a \s-1SPICE\s0 agent. This is currently only +supported on Windows guests. +.IP "\-\-spice\-ca\-file=" 4 +.IX Item "--spice-ca-file=" +Truststore file for secure connections +.Sp +This option is used to specify a .crt file containing the \s-1CA\s0 certificate with which +the \s-1SPICE\s0 server \s-1TLS\s0 certificates are signed. This is useful when using self-signed +\&\s-1TLS\s0 certificates rather than certificates signed by an official \s-1CA.\s0 +.IP "\-\-spice\-host\-subject=" 4 +.IX Item "--spice-host-subject=" +Subject of the host certificate (field=value pairs separated by commas) +.Sp +When using self-signed certificates, or when the guest is migrated between +different hosts, the subject/altSubject of the \s-1TLS\s0 certificate the \s-1SPICE\s0 +server will provide will not necessarily match the hostname we are connecting to. +This option makes it possible to override the expected subject of the \s-1TLS\s0 certificate. +.Sp +The subject must correspond to the \*(L"Subject:\*(R" line returned by: + openssl x509 \-noout \-text \-in server\-cert.pem +.IP "\-\-spice\-debug" 4 +.IX Item "--spice-debug" +Enable Spice-GTK debugging. This can also be toggled on with the +\&\s-1SPICE_DEBUG\s0 environment variable, or using G_MESSAGES_DEBUG=all +.IP "\-\-spice\-disable\-audio" 4 +.IX Item "--spice-disable-audio" +Disable audio support +.IP "\-\-spice\-disable\-usbredir" 4 +.IX Item "--spice-disable-usbredir" +Disable \s-1USB\s0 redirection support +.IP "\-\-spice\-usbredir\-auto\-redirect\-filter=" 4 +.IX Item "--spice-usbredir-auto-redirect-filter=" +Filter selecting \s-1USB\s0 devices to be auto-redirected when plugged in +.Sp +This filter specifies which \s-1USB\s0 devices should be automatically redirected +when they are plugged in during the lifetime of a \s-1SPICE\s0 session. +.Sp +A rule has the form of: +\&\f(CW\*(C`class,vendor,product,version,allow\*(C'\fR +.Sp +\&\-1 can be used instead of class, vendor, product or version in order to accept +any value. Several rules can be concatenated with '|': +\&\f(CW\*(C`rule1|rule2|rule3\*(C'\fR +.IP "\-\-spice\-usbredir\-redirect\-on\-connect=" 4 +.IX Item "--spice-usbredir-redirect-on-connect=" +Filter selecting \s-1USB\s0 devices to redirect on connect +.Sp +This filter specifies which \s-1USB\s0 devices should be automatically redirected +when a \s-1SPICE\s0 connection to a remote display has been established. +.IP "\-\-spice\-gtk\-version" 4 +.IX Item "--spice-gtk-version" +Display Spice-GTK version information +.IP "\-\-spice\-smartcard" 4 +.IX Item "--spice-smartcard" +Enable smartcard support +.IP "\-\-spice\-smartcard\-db=" 4 +.IX Item "--spice-smartcard-db=" +Path to the local certificate database to use for software smartcard certificates +.Sp +This option is only useful for testing purpose. Instead of having a hardware +smartcard reader, and a physical smartcard, you can specify a file containing 3 +certificates which will be used to emulate a smartcard in software. See +\&\f(CW\*(C`http://www.spice\-space.org/page/SmartcardUsage#Using_a_software_smartcard\*(C'\fR +for more details about how to generate these certificates. +.IP "\-\-spice\-smartcard\-certificates=" 4 +.IX Item "--spice-smartcard-certificates=" +Certificates to use for software smartcards (field=values separated by commas) +.Sp +This option is only useful for testing purpose. This allows to specify which +certificates from the certificate database specified with \-\-spice\-smartcard\-db +should be used for smartcard emulation. +.IP "\-\-spice\-cache\-size=" 4 +.IX Item "--spice-cache-size=" +Image cache size +.Sp +This option should only be used for testing/debugging. +.IP "\-\-spice\-glz\-window\-size=" 4 +.IX Item "--spice-glz-window-size=" +Glz compression history size +.Sp +This option should only be used for testing/debugging. +.SH "BUGS" +.IX Header "BUGS" +Report bugs to the mailing list \f(CW\*(C`http://lists.freedesktop.org/mailman/listinfo/spice\-devel\*(C'\fR +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +Copyright (C) 2011, 2014 Red Hat, Inc., and various contributors. +This is free software. You may redistribute copies of it under the terms of +the \s-1GNU\s0 Lesser General Public License +\&\f(CW\*(C`https://www.gnu.org/licenses/old\-licenses/lgpl\-2.1.html\*(C'\fR. +There is \s-1NO WARRANTY,\s0 to the extent permitted by law. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\f(CW\*(C`virt\-viewer(1)\*(C'\fR, the project website \f(CW\*(C`http://spice\-space.org\*(C'\fR diff --git a/man/spice-client.pod b/man/spice-client.pod new file mode 100644 index 0000000..69ea84c --- /dev/null +++ b/man/spice-client.pod @@ -0,0 +1,195 @@ +=head1 NAME + +Spice-GTK - a client-side library to access remote SPICE displays + +=head1 DESCRIPTION + +Spice-GTK is a library allowing access to remote displays over the SPICE +protocol. At the moment It's mainly used to access remote virtual machines. + +The Spice-GTK library provides a set of command line options which +can be used to tweak some SPICE-specific option. + +=head1 URI + +The most basic SPICE URI which can be used is in the form + spice://hostname.example.com:5900 + +This will try to initiate a SPICE connection to hostname.example.com +to port 5900. This connection will be unencrypted. This URI is +equivalent to + spice://hostname.example.com?port=5900 + +In order to start a TLS connection, one would use + spice://hostname.example.com?tls-port=5900 + +Other valid URI parameters are 'username' and 'password'. Be careful that +passing a password through a SPICE URI might cause the password to be +visible by any local user through 'ps'. + +Several parameters can be specified at once if they are separated +by & or ; + spice://hostname.example.com?port=5900;tls-port=5901 + +When using 'tls-port', it's recommended to not specify any non-TLS port. +If you give both 'port' and 'tls-port', make sure you use the +--spice-secure-channels options to indicate which channels must be secure. +Otherwise, Spice-GTK first attempts a connection to the non-TLS port, and +then try to use the TLS port. This means a man-in-the-middle could force +the whole SPICE session to go in clear text regardless of the TLS settings +of the SPICE server. + +=head1 OPTIONS + +The following options are accepted when running a SPICE client which +makes use of the default Spice-GTK options: + +=over 4 + +=item --spice-secure-channels= + +Force the specified channels to be secured + +This instructs the SPICE client that it must use a TLS connection for these +channels. If the server only offers non-TLS connections for these channels, +the client will not use these. If the special value "all" is used, this +indicates that all SPICE channels must be encrypted. + +The current SPICE channels are: main, display, inputs, cursor, playback, +record, smartcard, usbredir. + +=item --spice-disable-effects= + +Disable guest display effects + +This tells the SPICE client that it should attempt to disable some guest +features in order to lower bandwidth usage. This requires guest support, +usually through a SPICE agent. This is currently only supported on Windows +guests. + +"wallpaper" will disable the guest wallpaper, "font-smooth" will disable +font antialiasing, "animation" will try to disable some of the desktop +environment animations. "all" will attempt to disable everything which +can be disabled. + +=item --spice-color-depth=<16,32> + +Guest display color depth + +This tells the SPICE client that it should attempt to force the guest OS +color depth. A lower color depth should lower bandwith usage. This requires +guest support, usually through a SPICE agent. This is currently only +supported on Windows guests. + +=item --spice-ca-file= + +Truststore file for secure connections + +This option is used to specify a .crt file containing the CA certificate with which +the SPICE server TLS certificates are signed. This is useful when using self-signed +TLS certificates rather than certificates signed by an official CA. + + +=item --spice-host-subject= + +Subject of the host certificate (field=value pairs separated by commas) + +When using self-signed certificates, or when the guest is migrated between +different hosts, the subject/altSubject of the TLS certificate the SPICE +server will provide will not necessarily match the hostname we are connecting to. +This option makes it possible to override the expected subject of the TLS certificate. + +The subject must correspond to the "Subject:" line returned by: + openssl x509 -noout -text -in server-cert.pem + +=item --spice-debug + +Enable Spice-GTK debugging. This can also be toggled on with the +SPICE_DEBUG environment variable, or using G_MESSAGES_DEBUG=all + +=item --spice-disable-audio + +Disable audio support + +=item --spice-disable-usbredir + +Disable USB redirection support + +=item --spice-usbredir-auto-redirect-filter= + +Filter selecting USB devices to be auto-redirected when plugged in + +This filter specifies which USB devices should be automatically redirected +when they are plugged in during the lifetime of a SPICE session. + +A rule has the form of: +C + +-1 can be used instead of class, vendor, product or version in order to accept +any value. Several rules can be concatenated with '|': +C + +=item --spice-usbredir-redirect-on-connect= + +Filter selecting USB devices to redirect on connect + +This filter specifies which USB devices should be automatically redirected +when a SPICE connection to a remote display has been established. + +=item --spice-gtk-version + +Display Spice-GTK version information + +=item --spice-smartcard + +Enable smartcard support + +=item --spice-smartcard-db= + +Path to the local certificate database to use for software smartcard certificates + +This option is only useful for testing purpose. Instead of having a hardware +smartcard reader, and a physical smartcard, you can specify a file containing 3 +certificates which will be used to emulate a smartcard in software. See +C +for more details about how to generate these certificates. + +=item --spice-smartcard-certificates= + +Certificates to use for software smartcards (field=values separated by commas) + +This option is only useful for testing purpose. This allows to specify which +certificates from the certificate database specified with --spice-smartcard-db +should be used for smartcard emulation. + +=item --spice-cache-size= + +Image cache size + +This option should only be used for testing/debugging. + +=item --spice-glz-window-size= + +Glz compression history size + +This option should only be used for testing/debugging. + +=back + +=head1 BUGS + +Report bugs to the mailing list C + +=head1 COPYRIGHT + +Copyright (C) 2011, 2014 Red Hat, Inc., and various contributors. +This is free software. You may redistribute copies of it under the terms of +the GNU Lesser General Public License +C. +There is NO WARRANTY, to the extent permitted by law. + +=head1 SEE ALSO + +C, the project website C + +=cut diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..d300628 --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,8 @@ +2010-11-25 Marc-Andre Lureau + + * Added initial french translation for spicy and snappy. + +2010-11-24 Marc-Andre Lureau + + * Initial translation support. + diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..8921737 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +# keep this file sorted alphabetically, one language code per line +fr diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..fcd2c3b --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,221 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper +# Copyright (C) 2004-2008 Rodney Dawes +# +# This file may be copied and used freely without restrictions. It may +# be used in projects which are not available under a GNU Public License, +# but which still want to provide support for the GNU gettext functionality. +# +# - Modified by Owen Taylor to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize +# +# - Modified by Rodney Dawes for use with intltool +# +# We have the following line for use by intltoolize: +# INTLTOOL_MAKEFILE + +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +datarootdir = @datarootdir@ +libdir = @libdir@ +localedir = @localedir@ +subdir = po +install_sh = @install_sh@ +# Automake >= 1.8 provides @mkdir_p@. +# Until it can be supposed, use the safe fallback: +mkdir_p = $(install_sh) -d + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +MSGMERGE = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +ALL_LINGUAS = @ALL_LINGUAS@ + +PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) + +USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) + +USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) + +POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) + +DISTFILES = Makefile.in.in POTFILES.in $(POFILES) +EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS + +POTFILES = \ +# This comment gets stripped out + +CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) + +.SUFFIXES: +.SUFFIXES: .po .pox .gmo .mo .msg .cat + +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +INTLTOOL_V_MSGFMT = $(INTLTOOL__v_MSGFMT_$(V)) +INTLTOOL__v_MSGFMT_= $(INTLTOOL__v_MSGFMT_$(AM_DEFAULT_VERBOSITY)) +INTLTOOL__v_MSGFMT_0 = @echo " MSGFMT" $@; + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $* $(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(INTLTOOL_V_MSGFMT)$(MSGFMT) -o $@ $< + +.po.gmo: + $(INTLTOOL_V_MSGFMT)file=`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && gencat $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) +all-no: + +$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-data +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + dir=$(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $$dir; \ + if test -r $$lang.gmo; then \ + $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $(srcdir)/$$lang.gmo as" \ + "$$dir/$(GETTEXT_PACKAGE).mo"; \ + fi; \ + if test -r $$lang.gmo.m; then \ + $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + if test -r $(srcdir)/$$lang.gmo.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ + $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $(srcdir)/$$lang.gmo.m as" \ + "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + true; \ + fi; \ + fi; \ + done + +# Empty stubs to satisfy archaic automake needs +dvi info ctags tags CTAGS TAGS ID: + +# Define this as empty until I found a useful application. +install-exec installcheck: + +uninstall: + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ + done + +check: all $(GETTEXT_PACKAGE).pot + rm -f missing notexist + srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m + if [ -r missing -o -r notexist ]; then \ + exit 1; \ + fi + +mostlyclean: + rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp + rm -f .intltool-merge-cache + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES stamp-it + rm -f *.mo *.msg *.cat *.cat.m *.gmo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f Makefile.in.in + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: $(DISTFILES) + dists="$(DISTFILES)"; \ + extra_dists="$(EXTRA_DISTFILES)"; \ + for file in $$extra_dists; do \ + test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ + done; \ + for file in $$dists; do \ + test -f $$file || file="$(srcdir)/$$file"; \ + ln $$file $(distdir) 2> /dev/null \ + || cp -p $$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + tmpdir=`pwd`; \ + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + echo "$$lang:"; \ + result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ + if $$result; then \ + if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.gmo failed!"; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi; \ + done + +Makefile POTFILES: stamp-it + @if test ! -f $@; then \ + rm -f stamp-it; \ + $(MAKE) stamp-it; \ + fi + +stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..ad12609 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,8 @@ +src/channel-usbredir.c +src/desktop-integration.c +src/spice-channel.c +src/spice-cmdline.c +src/spice-option.c +src/usb-device-manager.c +src/usb-device-widget.c +src/usbutil.c diff --git a/po/POTFILES.skip b/po/POTFILES.skip new file mode 100644 index 0000000..0dd1912 --- /dev/null +++ b/po/POTFILES.skip @@ -0,0 +1,2 @@ +spice-common/python_modules/spice_parser.py +spice-common/spice_codegen.py diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..7a8f3ec --- /dev/null +++ b/po/fr.po @@ -0,0 +1,235 @@ +# French translation for spice. +# Copyright (C) 2010 Listed translators +# This file is distributed under the same license as the gtk-vnc package. +# +# Marc-André Lureau , 2010 +# +msgid "" +msgstr "" +"Project-Id-Version: spice master fr\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-11-25 03:25+0100\n" +"PO-Revision-Date: 2010-11-25 03:43+0100\n" +"Last-Translator: Marc-André Lureau \n" +"Language-Team: GNOME French Team \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: ../gtk/spicy.c:129 +msgid "Hostname" +msgstr "Nom de l'hôte" + +#: ../gtk/spicy.c:130 +msgid "Port" +msgstr "Port" + +#: ../gtk/spicy.c:131 +msgid "TLS Port" +msgstr "Port TLS" + +#. Create the widgets +#: ../gtk/spicy.c:140 +msgid "Connect" +msgstr "Connexion" + +#: ../gtk/spicy.c:196 +#, c-format +msgid "Use Shift+F12 to ungrab mouse." +msgstr "Utiliser Shift+F12 pour désaisir la souris." + +#: ../gtk/spicy.c:198 +#, c-format +msgid "mouse: %s, agent: %s" +msgstr "souris: %s, agent: %s" + +#: ../gtk/spicy.c:257 ../gtk/spicy.c:683 +msgid "yes" +msgstr "oui" + +#: ../gtk/spicy.c:257 ../gtk/spicy.c:683 +msgid "no" +msgstr "non" + +#: ../gtk/spicy.c:265 +msgid "" +"gtk client app for the\n" +"spice remote desktop protocol" +msgstr "" +"Application Gtk de connexion\n" +"au serveur de bureau spice" + +#: ../gtk/spicy.c:360 +msgid "_Connect ..." +msgstr "_Ouvrir une session..." + +#: ../gtk/spicy.c:366 +msgid "_Close" +msgstr "_Quitter" + +#: ../gtk/spicy.c:374 +msgid "_Copy to guest" +msgstr "_Copier dans l'invité" + +#: ../gtk/spicy.c:380 +msgid "_Paste from guest" +msgstr "Coller dans l'invité" + +#: ../gtk/spicy.c:388 +msgid "_Fullscreen" +msgstr "_Plein écran" + +#: ../gtk/spicy.c:395 +msgid "_Ungrab mouse" +msgstr "_Désaisir la souris" + +#: ../gtk/spicy.c:403 +msgid "_About ..." +msgstr "_À propos" + +#: ../gtk/spicy.c:411 +msgid "Grab keyboard when active and focused" +msgstr "Saisir le clavier après focus" + +#: ../gtk/spicy.c:415 +msgid "Grab mouse in server mode (no tabled/vdagent)" +msgstr "Saisir la souris en mode serveur (pas d'agent)" + +#: ../gtk/spicy.c:419 +msgid "Resize guest to match window size" +msgstr "Redimensionner l'invité à la taille de fenêtre" + +#: ../gtk/spicy.c:423 +msgid "Automagic clipboard sharing between host and guest" +msgstr "Partage de presse-papiers automatique" + +#: ../gtk/spicy.c:485 +#, c-format +msgid "spice display %d" +msgstr "écran spice %d" + +#: ../gtk/spicy.c:542 +msgid "?" +msgstr "?" + +#. FIXME i18 +#: ../gtk/spicy.c:639 +msgid "Authentication" +msgstr "Authentification" + +#: ../gtk/spicy.c:640 +msgid "Please enter the spice server password" +msgstr "Entrez le mot de passe du serveur spice" + +#: ../gtk/spicy.c:694 +msgid "SCROLL" +msgstr "DÉFIL" + +#: ../gtk/spicy.c:696 +msgid "CAPS" +msgstr "VERR.MAJ" + +#: ../gtk/spicy.c:698 +msgid "NUM" +msgstr "VERR.NUM" + +#: ../gtk/spicy.c:831 +msgid "open in full screen mode" +msgstr "Ouvrir en plein-écran" + +#: ../gtk/spicy.c:849 +msgid "- spice client application" +msgstr "- application client spice" + +#: ../gtk/spicy.c:854 ../gtk/snappy.c:144 +#, c-format +msgid "option parsing failed: %s\n" +msgstr "échec d'analyse des options: %s\n" + +#: ../gtk/snappy.c:60 +#, c-format +msgid "snappy: can't open %s: %s\n" +msgstr "snappy: impossible d'ouvrir %s: %s\n" + +#: ../gtk/snappy.c:88 +#, c-format +msgid "unsupported spice surface format %d\n" +msgstr "format de surface spice non supporté %d\n" + +#: ../gtk/snappy.c:93 +#, c-format +msgid "wrote screen shot to %s\n" +msgstr "capture d'écran sauvée dans %s\n" + +#: ../gtk/snappy.c:123 +msgid "output file name (*.ppm)" +msgstr "nom de fichier d'enregistrement (*.ppm)" + +#: ../gtk/snappy.c:124 +msgid "" +msgstr "" + +#. parse opts +#: ../gtk/snappy.c:140 +msgid " - write screen shots in ppm format" +msgstr " - sauve des capture d'écran au format ppm" + +#: ../gtk/snappy.c:157 +#, c-format +msgid "spice_session_connect failed\n" +msgstr "spice_session_connect a échoué\n" + +#: ../gtk/spice-cmdline.c:39 +msgid "spice server uri" +msgstr "uri du serveur spice" + +#: ../gtk/spice-cmdline.c:40 +msgid "" +msgstr "" + +#: ../gtk/spice-cmdline.c:46 +msgid "spice server address" +msgstr "adresse du serveur spice" + +#: ../gtk/spice-cmdline.c:47 +msgid "" +msgstr "" + +#: ../gtk/spice-cmdline.c:53 +msgid "spice server port" +msgstr "port du serveur spice" + +#: ../gtk/spice-cmdline.c:54 ../gtk/spice-cmdline.c:61 +msgid "" +msgstr "" + +#: ../gtk/spice-cmdline.c:60 +msgid "spice server secure port" +msgstr "port sécurisé du serveur spice" + +#: ../gtk/spice-cmdline.c:66 +msgid "truststore file for secure connections" +msgstr "fichier truststore pour les connexions sécurisées" + +#: ../gtk/spice-cmdline.c:67 +#, fuzzy +msgid "" +msgstr "" + +#: ../gtk/spice-cmdline.c:73 +msgid "server password" +msgstr "mot de passe du serveur" + +#: ../gtk/spice-cmdline.c:74 +msgid "" +msgstr "" + +#: ../gtk/spice-cmdline.c:86 +msgid "Spice Options:" +msgstr "Options Spice:" + +#: ../gtk/spice-cmdline.c:87 +msgid "Show spice Options" +msgstr "Affiche les options de spice" diff --git a/spice-client-glib-2.0.pc.in b/spice-client-glib-2.0.pc.in new file mode 100644 index 0000000..27d6886 --- /dev/null +++ b/spice-client-glib-2.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: spice-client-glib-2.0 +Description: SPICE Client GLib 2.0 library +Version: @VERSION@ + +Requires: spice-protocol +Requires.private: @SPICE_GLIB_REQUIRES@ +Libs: -L${libdir} -lspice-client-glib-2.0 +Cflags: -I${includedir}/spice-client-glib-2.0 diff --git a/spice-client-gtk-3.0.pc.in b/spice-client-gtk-3.0.pc.in new file mode 100644 index 0000000..7bad0c8 --- /dev/null +++ b/spice-client-gtk-3.0.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: spice-client-gtk-3.0 +Description: SPICE Client Gtk 3.0 library +Version: @VERSION@ + +Requires: @SPICE_GTK_REQUIRES@ spice-client-glib-2.0 +Libs: -L${libdir} -lspice-client-gtk-3.0 +Cflags: -I${includedir}/spice-client-gtk-3.0 diff --git a/spice-common/COPYING b/spice-common/COPYING new file mode 100644 index 0000000..e5ab03e --- /dev/null +++ b/spice-common/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/spice-common/Makefile.am b/spice-common/Makefile.am new file mode 100644 index 0000000..63d7956 --- /dev/null +++ b/spice-common/Makefile.am @@ -0,0 +1,28 @@ +NULL = +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = python_modules common tests + +EXTRA_DIST = \ + spice_codegen.py \ + spice.proto \ + spice1.proto \ + $(NULL) + +DISTCLEANFILES = *.pyc + +MAINTAINERCLEANFILES = \ + $(srcdir)/INSTALL \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/build-aux \ + $(srcdir)/config.h.in \ + $(srcdir)/m4/libtool.m4 \ + $(srcdir)/m4/ltoptions.m4 \ + $(srcdir)/m4/ltsugar.m4 \ + $(srcdir)/m4/ltversion.m4 \ + $(srcdir)/m4/lt~obsolete.m4 \ + `find "$(srcdir)" -type f -name Makefile.in -print` \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/spice-common/Makefile.in b/spice-common/Makefile.in new file mode 100644 index 0000000..2226253 --- /dev/null +++ b/spice-common/Makefile.in @@ -0,0 +1,872 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/build-aux/ar-lib $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing COPYING build-aux/ar-lib \ + build-aux/compile build-aux/config.guess build-aux/config.sub \ + build-aux/install-sh build-aux/ltmain.sh build-aux/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CELT051_CFLAGS = @CELT051_CFLAGS@ +CELT051_LIBS = @CELT051_LIBS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPUS_CFLAGS = @OPUS_CFLAGS@ +OPUS_LIBS = @OPUS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOCOL_CFLAGS = @PROTOCOL_CFLAGS@ +PROTOCOL_LIBS = @PROTOCOL_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_COMMON_CFLAGS = @SPICE_COMMON_CFLAGS@ +SPICE_COMMON_LIBS = @SPICE_COMMON_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = python_modules common tests +EXTRA_DIST = \ + spice_codegen.py \ + spice.proto \ + spice1.proto \ + $(NULL) + +DISTCLEANFILES = *.pyc +MAINTAINERCLEANFILES = \ + $(srcdir)/INSTALL \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/build-aux \ + $(srcdir)/config.h.in \ + $(srcdir)/m4/libtool.m4 \ + $(srcdir)/m4/ltoptions.m4 \ + $(srcdir)/m4/ltsugar.m4 \ + $(srcdir)/m4/ltversion.m4 \ + $(srcdir)/m4/lt~obsolete.m4 \ + `find "$(srcdir)" -type f -name Makefile.in -print` \ + $(NULL) + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/spice-common/aclocal.m4 b/spice-common/aclocal.m4 new file mode 100644 index 0000000..fa3db28 --- /dev/null +++ b/spice-common/aclocal.m4 @@ -0,0 +1,1832 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_AR([ACT-IF-FAIL]) +# ------------------------- +# Try to determine the archiver interface, and trigger the ar-lib wrapper +# if it is needed. If the detection of archiver interface fails, run +# ACT-IF-FAIL (default is to abort configure with a proper error message). +AC_DEFUN([AM_PROG_AR], +[AC_BEFORE([$0], [LT_INIT])dnl +AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([ar-lib])dnl +AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) +: ${AR=ar} + +AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], + [AC_LANG_PUSH([C]) + am_cv_ar_interface=ar + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], + [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + ]) + AC_LANG_POP([C])]) + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + m4_default([$1], + [AC_MSG_ERROR([could not determine $AR interface])]) + ;; +esac +AC_SUBST([AR])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_COND_IF -*- Autoconf -*- + +# Copyright (C) 2008-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_COND_IF +# _AM_COND_ELSE +# _AM_COND_ENDIF +# -------------- +# These macros are only used for tracing. +m4_define([_AM_COND_IF]) +m4_define([_AM_COND_ELSE]) +m4_define([_AM_COND_ENDIF]) + +# AM_COND_IF(COND, [IF-TRUE], [IF-FALSE]) +# --------------------------------------- +# If the shell condition COND is true, execute IF-TRUE, otherwise execute +# IF-FALSE. Allow automake to learn about conditional instantiating macros +# (the AC_CONFIG_FOOS). +AC_DEFUN([AM_COND_IF], +[m4_ifndef([_AM_COND_VALUE_$1], + [m4_fatal([$0: no such condition "$1"])])dnl +_AM_COND_IF([$1])dnl +if test -z "$$1_TRUE"; then : + m4_n([$2])[]dnl +m4_ifval([$3], +[_AM_COND_ELSE([$1])dnl +else + $3 +])dnl +_AM_COND_ENDIF([$1])dnl +fi[]dnl +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# -*- Autoconf -*- +# Obsolete and "removed" macros, that must however still report explicit +# error messages when used, to smooth transition. +# +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +AC_DEFUN([AM_CONFIG_HEADER], +[AC_DIAGNOSE([obsolete], +['$0': this macro is obsolete. +You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl +AC_CONFIG_HEADERS($@)]) + +AC_DEFUN([AM_PROG_CC_STDC], +[AC_PROG_CC +am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc +AC_DIAGNOSE([obsolete], +['$0': this macro is obsolete. +You should simply use the 'AC][_PROG_CC' macro instead. +Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', +but upon 'ac_cv_prog_cc_stdc'.])]) + +AC_DEFUN([AM_C_PROTOTYPES], + [AC_FATAL([automatic de-ANSI-fication support has been removed])]) +AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------- +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. +# +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. +# +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). +# +# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. +AC_DEFUN([AM_PATH_PYTHON], + [ + dnl Find a Python interpreter. Python versions prior to 2.0 are not + dnl supported. (2.0 was released on October 16, 2000). + m4_define_default([_AM_PYTHON_INTERPRETER_LIST], +[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl + python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) + + AC_ARG_VAR([PYTHON], [the Python interpreter]) + + m4_if([$1],[],[ + dnl No version check is needed. + # Find any Python interpreter. + if test -z "$PYTHON"; then + AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) + fi + am_display_PYTHON=python + ], [ + dnl A version check is needed. + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + AC_MSG_CHECKING([whether $PYTHON version is >= $1]) + AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Python interpreter is too old])]) + am_display_PYTHON=$PYTHON + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + AC_CACHE_CHECK([for a Python interpreter with version >= $1], + [am_cv_pathless_PYTHON],[ + for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do + test "$am_cv_pathless_PYTHON" = none && break + AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) + done]) + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + if test "$am_cv_pathless_PYTHON" = none; then + PYTHON=: + else + AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) + fi + am_display_PYTHON=$am_cv_pathless_PYTHON + fi + ]) + + if test "$PYTHON" = :; then + dnl Run any user-specified action, or abort. + m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) + else + + dnl Query Python for its version number. Getting [:3] seems to be + dnl the best way to do this; it's what "site.py" does in the standard + dnl library. + + AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], + [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) + AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made + dnl distinct variables so they can be overridden if need be. However, + dnl general consensus is that you shouldn't need this ability. + + AC_SUBST([PYTHON_PREFIX], ['${prefix}']) + AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) + + dnl At times (like when building shared libraries) you may want + dnl to know which OS platform Python thinks this is. + + AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], + [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) + AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + dnl Set up 4 directories: + + dnl pythondir -- where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behavior + dnl is more consistent with lispdir.m4 for example. + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON script directory], + [am_cv_python_pythondir], + [if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pythondir], [$am_cv_python_pythondir]) + + dnl pkgpythondir -- $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + + AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) + dnl Query distutils for this directory. + AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], + [am_cv_python_pyexecdir], + [if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) + AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + + AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) + + dnl Run any user-specified action. + $2 + fi + +]) + + +# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# This test uses sys.hexversion instead of the string equivalent (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). +AC_DEFUN([AM_PYTHON_CHECK_VERSION], + [prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] +sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/ax_python_module.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/spice-deps.m4]) diff --git a/spice-common/build-aux/ar-lib b/spice-common/build-aux/ar-lib new file mode 100755 index 0000000..463b9ec --- /dev/null +++ b/spice-common/build-aux/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010-2014 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/spice-common/build-aux/config.guess b/spice-common/build-aux/config.guess new file mode 100755 index 0000000..dbfb978 --- /dev/null +++ b/spice-common/build-aux/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) 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 -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # 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 ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/spice-common/build-aux/config.sub b/spice-common/build-aux/config.sub new file mode 100755 index 0000000..6467c95 --- /dev/null +++ b/spice-common/build-aux/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/spice-common/build-aux/depcomp b/spice-common/build-aux/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/spice-common/build-aux/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/spice-common/build-aux/install-sh b/spice-common/build-aux/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/spice-common/build-aux/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/spice-common/build-aux/ltmain.sh b/spice-common/build-aux/ltmain.sh new file mode 100644 index 0000000..0f0a2da --- /dev/null +++ b/spice-common/build-aux/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/spice-common/build-aux/missing b/spice-common/build-aux/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/spice-common/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/spice-common/build-aux/test-driver b/spice-common/build-aux/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/spice-common/build-aux/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/spice-common/common/Makefile.am b/spice-common/common/Makefile.am new file mode 100644 index 0000000..2dd56f3 --- /dev/null +++ b/spice-common/common/Makefile.am @@ -0,0 +1,141 @@ +NULL = + +# Avoid need for python(pyparsing) by end users +CLIENT_MARSHALLERS = \ + generated_client_demarshallers.c \ + generated_client_demarshallers1.c \ + generated_client_marshallers.c \ + generated_client_marshallers1.c \ + $(NULL) + +SERVER_MARSHALLERS = \ + generated_server_demarshallers.c \ + generated_server_marshallers.c \ + generated_server_marshallers.h \ + $(NULL) + +BUILT_SOURCES = $(CLIENT_MARSHALLERS) $(SERVER_MARSHALLERS) + +noinst_LTLIBRARIES = libspice-common.la libspice-common-server.la libspice-common-client.la +libspice_common_la_SOURCES = \ + backtrace.c \ + backtrace.h \ + bitops.h \ + canvas_utils.c \ + canvas_utils.h \ + client_demarshallers.h \ + client_marshallers.h \ + draw.h \ + lines.c \ + lines.h \ + log.c \ + log.h \ + lz.c \ + lz.h \ + lz_common.h \ + lz_config.h \ + macros.h \ + marshaller.c \ + marshaller.h \ + mem.c \ + mem.h \ + messages.h \ + pixman_utils.c \ + pixman_utils.h \ + quic.c \ + quic.h \ + quic_config.h \ + rect.h \ + region.c \ + region.h \ + ring.h \ + rop3.c \ + rop3.h \ + snd_codec.c \ + snd_codec.h \ + spice_common.h \ + ssl_verify.c \ + ssl_verify.h \ + verify.h \ + $(NULL) + +# These 2 files are not build as part of spice-common +# build system, but modules using spice-common will build +# them with the appropriate options. We need to let automake +# know that these are source files so that it can properly +# track these files dependencies +EXTRA_libspice_common_la_SOURCES = \ + sw_canvas.c \ + sw_canvas.h \ + $(NULL) + +libspice_common_client_la_SOURCES = \ + $(CLIENT_MARSHALLERS) \ + $(NULL) + +libspice_common_server_la_SOURCES = \ + $(SERVER_MARSHALLERS) \ + $(NULL) + +libspice_common_server_la_CFLAGS = -DFIXME_SERVER_SMARTCARD + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(SPICE_COMMON_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) + +libspice_common_la_LIBADD = \ + $(SPICE_COMMON_LIBS) \ + $(NULL) + +MARSHALLERS_DEPS = \ + $(top_srcdir)/python_modules/__init__.py \ + $(top_srcdir)/python_modules/codegen.py \ + $(top_srcdir)/python_modules/demarshal.py \ + $(top_srcdir)/python_modules/marshal.py \ + $(top_srcdir)/python_modules/ptypes.py \ + $(top_srcdir)/python_modules/spice_parser.py \ + $(top_srcdir)/spice_codegen.py \ + $(NULL) + +# Note despite being autogenerated these are not part of CLEANFILES, they are +# actually a part of EXTRA_DIST, to avoid the need for pyparser by end users +generated_client_demarshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common/messages.h $< $@ >/dev/null + +generated_client_demarshallers1.c: $(top_srcdir)/spice1.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common/messages.h --prefix 1 --ptrsize 8 $< $@ >/dev/null + +generated_client_marshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include common/messages.h --include client_marshallers.h --client $< $@ >/dev/null + +generated_client_marshallers1.c: $(top_srcdir)/spice1.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include common/messages.h --include client_marshallers.h --client --prefix 1 --ptrsize 8 $< $@ >/dev/null + +generated_server_demarshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include common/messages.h $< $@ >/dev/null + +STRUCTS = -M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlend -M Composite +generated_server_marshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server --include common/messages.h $< $@ >/dev/null + +generated_server_marshallers.h: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server --include common/messages.h -H $< $@ >/dev/null + +EXTRA_DIST = \ + $(CLIENT_MARSHALLERS) \ + $(SERVER_MARSHALLERS) \ + canvas_base.c \ + canvas_base.h \ + gdi_canvas.c \ + gdi_canvas.h \ + lz_compress_tmpl.c \ + lz_decompress_tmpl.c \ + quic_family_tmpl.c \ + quic_rgb_tmpl.c \ + quic_tmpl.c \ + snd_codec.h \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/spice-common/common/Makefile.in b/spice-common/common/Makefile.in new file mode 100644 index 0000000..4c27455 --- /dev/null +++ b/spice-common/common/Makefile.in @@ -0,0 +1,828 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = common +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libspice_common_client_la_LIBADD = +am__objects_1 = +am__objects_2 = generated_client_demarshallers.lo \ + generated_client_demarshallers1.lo \ + generated_client_marshallers.lo \ + generated_client_marshallers1.lo $(am__objects_1) +am_libspice_common_client_la_OBJECTS = $(am__objects_2) \ + $(am__objects_1) +libspice_common_client_la_OBJECTS = \ + $(am_libspice_common_client_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libspice_common_server_la_LIBADD = +am__objects_3 = \ + libspice_common_server_la-generated_server_demarshallers.lo \ + libspice_common_server_la-generated_server_marshallers.lo \ + $(am__objects_1) +am_libspice_common_server_la_OBJECTS = $(am__objects_3) \ + $(am__objects_1) +libspice_common_server_la_OBJECTS = \ + $(am_libspice_common_server_la_OBJECTS) +libspice_common_server_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libspice_common_server_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__DEPENDENCIES_1 = +libspice_common_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_libspice_common_la_OBJECTS = backtrace.lo canvas_utils.lo lines.lo \ + log.lo lz.lo marshaller.lo mem.lo pixman_utils.lo quic.lo \ + region.lo rop3.lo snd_codec.lo ssl_verify.lo $(am__objects_1) +libspice_common_la_OBJECTS = $(am_libspice_common_la_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libspice_common_client_la_SOURCES) \ + $(libspice_common_server_la_SOURCES) \ + $(libspice_common_la_SOURCES) \ + $(EXTRA_libspice_common_la_SOURCES) +DIST_SOURCES = $(libspice_common_client_la_SOURCES) \ + $(libspice_common_server_la_SOURCES) \ + $(libspice_common_la_SOURCES) \ + $(EXTRA_libspice_common_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CELT051_CFLAGS = @CELT051_CFLAGS@ +CELT051_LIBS = @CELT051_LIBS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPUS_CFLAGS = @OPUS_CFLAGS@ +OPUS_LIBS = @OPUS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOCOL_CFLAGS = @PROTOCOL_CFLAGS@ +PROTOCOL_LIBS = @PROTOCOL_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_COMMON_CFLAGS = @SPICE_COMMON_CFLAGS@ +SPICE_COMMON_LIBS = @SPICE_COMMON_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = + +# Avoid need for python(pyparsing) by end users +CLIENT_MARSHALLERS = \ + generated_client_demarshallers.c \ + generated_client_demarshallers1.c \ + generated_client_marshallers.c \ + generated_client_marshallers1.c \ + $(NULL) + +SERVER_MARSHALLERS = \ + generated_server_demarshallers.c \ + generated_server_marshallers.c \ + generated_server_marshallers.h \ + $(NULL) + +BUILT_SOURCES = $(CLIENT_MARSHALLERS) $(SERVER_MARSHALLERS) +noinst_LTLIBRARIES = libspice-common.la libspice-common-server.la libspice-common-client.la +libspice_common_la_SOURCES = \ + backtrace.c \ + backtrace.h \ + bitops.h \ + canvas_utils.c \ + canvas_utils.h \ + client_demarshallers.h \ + client_marshallers.h \ + draw.h \ + lines.c \ + lines.h \ + log.c \ + log.h \ + lz.c \ + lz.h \ + lz_common.h \ + lz_config.h \ + macros.h \ + marshaller.c \ + marshaller.h \ + mem.c \ + mem.h \ + messages.h \ + pixman_utils.c \ + pixman_utils.h \ + quic.c \ + quic.h \ + quic_config.h \ + rect.h \ + region.c \ + region.h \ + ring.h \ + rop3.c \ + rop3.h \ + snd_codec.c \ + snd_codec.h \ + spice_common.h \ + ssl_verify.c \ + ssl_verify.h \ + verify.h \ + $(NULL) + + +# These 2 files are not build as part of spice-common +# build system, but modules using spice-common will build +# them with the appropriate options. We need to let automake +# know that these are source files so that it can properly +# track these files dependencies +EXTRA_libspice_common_la_SOURCES = \ + sw_canvas.c \ + sw_canvas.h \ + $(NULL) + +libspice_common_client_la_SOURCES = \ + $(CLIENT_MARSHALLERS) \ + $(NULL) + +libspice_common_server_la_SOURCES = \ + $(SERVER_MARSHALLERS) \ + $(NULL) + +libspice_common_server_la_CFLAGS = -DFIXME_SERVER_SMARTCARD +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(SPICE_COMMON_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) + +libspice_common_la_LIBADD = \ + $(SPICE_COMMON_LIBS) \ + $(NULL) + +MARSHALLERS_DEPS = \ + $(top_srcdir)/python_modules/__init__.py \ + $(top_srcdir)/python_modules/codegen.py \ + $(top_srcdir)/python_modules/demarshal.py \ + $(top_srcdir)/python_modules/marshal.py \ + $(top_srcdir)/python_modules/ptypes.py \ + $(top_srcdir)/python_modules/spice_parser.py \ + $(top_srcdir)/spice_codegen.py \ + $(NULL) + +STRUCTS = -M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlend -M Composite +EXTRA_DIST = \ + $(CLIENT_MARSHALLERS) \ + $(SERVER_MARSHALLERS) \ + canvas_base.c \ + canvas_base.h \ + gdi_canvas.c \ + gdi_canvas.h \ + lz_compress_tmpl.c \ + lz_decompress_tmpl.c \ + quic_family_tmpl.c \ + quic_rgb_tmpl.c \ + quic_tmpl.c \ + snd_codec.h \ + $(NULL) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign common/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign common/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libspice-common-client.la: $(libspice_common_client_la_OBJECTS) $(libspice_common_client_la_DEPENDENCIES) $(EXTRA_libspice_common_client_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libspice_common_client_la_OBJECTS) $(libspice_common_client_la_LIBADD) $(LIBS) + +libspice-common-server.la: $(libspice_common_server_la_OBJECTS) $(libspice_common_server_la_DEPENDENCIES) $(EXTRA_libspice_common_server_la_DEPENDENCIES) + $(AM_V_CCLD)$(libspice_common_server_la_LINK) $(libspice_common_server_la_OBJECTS) $(libspice_common_server_la_LIBADD) $(LIBS) + +libspice-common.la: $(libspice_common_la_OBJECTS) $(libspice_common_la_DEPENDENCIES) $(EXTRA_libspice_common_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libspice_common_la_OBJECTS) $(libspice_common_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canvas_utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_client_demarshallers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_client_demarshallers1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_client_marshallers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generated_client_marshallers1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspice_common_server_la-generated_server_demarshallers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspice_common_server_la-generated_server_marshallers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lines.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lz.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/marshaller.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pixman_utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/region.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rop3.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snd_codec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_verify.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sw_canvas.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libspice_common_server_la-generated_server_demarshallers.lo: generated_server_demarshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspice_common_server_la_CFLAGS) $(CFLAGS) -MT libspice_common_server_la-generated_server_demarshallers.lo -MD -MP -MF $(DEPDIR)/libspice_common_server_la-generated_server_demarshallers.Tpo -c -o libspice_common_server_la-generated_server_demarshallers.lo `test -f 'generated_server_demarshallers.c' || echo '$(srcdir)/'`generated_server_demarshallers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspice_common_server_la-generated_server_demarshallers.Tpo $(DEPDIR)/libspice_common_server_la-generated_server_demarshallers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='generated_server_demarshallers.c' object='libspice_common_server_la-generated_server_demarshallers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspice_common_server_la_CFLAGS) $(CFLAGS) -c -o libspice_common_server_la-generated_server_demarshallers.lo `test -f 'generated_server_demarshallers.c' || echo '$(srcdir)/'`generated_server_demarshallers.c + +libspice_common_server_la-generated_server_marshallers.lo: generated_server_marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspice_common_server_la_CFLAGS) $(CFLAGS) -MT libspice_common_server_la-generated_server_marshallers.lo -MD -MP -MF $(DEPDIR)/libspice_common_server_la-generated_server_marshallers.Tpo -c -o libspice_common_server_la-generated_server_marshallers.lo `test -f 'generated_server_marshallers.c' || echo '$(srcdir)/'`generated_server_marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspice_common_server_la-generated_server_marshallers.Tpo $(DEPDIR)/libspice_common_server_la-generated_server_marshallers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='generated_server_marshallers.c' object='libspice_common_server_la-generated_server_marshallers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspice_common_server_la_CFLAGS) $(CFLAGS) -c -o libspice_common_server_la-generated_server_marshallers.lo `test -f 'generated_server_marshallers.c' || echo '$(srcdir)/'`generated_server_marshallers.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Note despite being autogenerated these are not part of CLEANFILES, they are +# actually a part of EXTRA_DIST, to avoid the need for pyparser by end users +generated_client_demarshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common/messages.h $< $@ >/dev/null + +generated_client_demarshallers1.c: $(top_srcdir)/spice1.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common/messages.h --prefix 1 --ptrsize 8 $< $@ >/dev/null + +generated_client_marshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include common/messages.h --include client_marshallers.h --client $< $@ >/dev/null + +generated_client_marshallers1.c: $(top_srcdir)/spice1.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include common/messages.h --include client_marshallers.h --client --prefix 1 --ptrsize 8 $< $@ >/dev/null + +generated_server_demarshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include common/messages.h $< $@ >/dev/null +generated_server_marshallers.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server --include common/messages.h $< $@ >/dev/null + +generated_server_marshallers.h: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server --include common/messages.h -H $< $@ >/dev/null + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/spice-common/common/backtrace.c b/spice-common/common/backtrace.c new file mode 100644 index 0000000..6e0d61b --- /dev/null +++ b/spice-common/common/backtrace.c @@ -0,0 +1,132 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +/* + * Taken from xserver os/backtrace.c: + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "spice_common.h" + +#include +#include +#include +#include +#ifndef __MINGW32__ +#include +#endif + +#define GSTACK_PATH "/usr/bin/gstack" + +#if HAVE_EXECINFO_H +#include + +static void spice_backtrace_backtrace(void) +{ + void *array[100]; + int size; + + size = backtrace(array, sizeof(array)/sizeof(array[0])); + backtrace_symbols_fd(array, size, STDERR_FILENO); +} +#else +static void spice_backtrace_backtrace(void) +{ +} +#endif + +/* XXX perhaps gstack can be available in windows but pipe/waitpid isn't, + * so until it is ported properly just compile it out, we lose the + * backtrace only. */ +#ifndef __MINGW32__ +static int spice_backtrace_gstack(void) +{ + pid_t kidpid; + int pipefd[2]; + + if (pipe(pipefd) != 0) { + return -1; + } + + kidpid = fork(); + + if (kidpid == -1) { + /* ERROR */ + return -1; + } else if (kidpid == 0) { + /* CHILD */ + char parent[16]; + + close(STDIN_FILENO); + close(STDOUT_FILENO); + dup2(pipefd[1],STDOUT_FILENO); + close(STDERR_FILENO); + + snprintf(parent, sizeof(parent), "%d", getppid()); + execle(GSTACK_PATH, "gstack", parent, NULL, NULL); + exit(1); + } else { + /* PARENT */ + char btline[256]; + int kidstat; + int bytesread; + int done = 0; + + close(pipefd[1]); + + while (!done) { + bytesread = read(pipefd[0], btline, sizeof(btline) - 1); + + if (bytesread > 0) { + btline[bytesread] = 0; + fprintf(stderr, "%s", btline); + } + else if ((bytesread == 0) || + ((errno != EINTR) && (errno != EAGAIN))) { + done = 1; + } + } + close(pipefd[0]); + waitpid(kidpid, &kidstat, 0); + if (kidstat != 0) + return -1; + } + return 0; +} +#else +static int spice_backtrace_gstack(void) +{ + /* empty failing implementation */ + return -1; +} +#endif + +void spice_backtrace(void) +{ + int ret = -1; + + if (!access(GSTACK_PATH, X_OK)) { + ret = spice_backtrace_gstack(); + } + if (ret != 0) { + spice_backtrace_backtrace(); + } +} diff --git a/spice-common/common/backtrace.h b/spice-common/common/backtrace.h new file mode 100644 index 0000000..894c027 --- /dev/null +++ b/spice-common/common/backtrace.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef BACKTRACE_H +#define BACKTRACE_H + +#include + +SPICE_BEGIN_DECLS + +#if defined(WIN32) && !defined(__MINGW32__) +#define spice_backtrace() +#else +void spice_backtrace(void); +#endif + +SPICE_END_DECLS + +#endif // BACKTRACE_H diff --git a/spice-common/common/bitops.h b/spice-common/common/bitops.h new file mode 100644 index 0000000..eb294fe --- /dev/null +++ b/spice-common/common/bitops.h @@ -0,0 +1,87 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef BITOPS_H +#define BITOPS_H + +#include + +SPICE_BEGIN_DECLS + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +static inline int spice_bit_find_msb(unsigned int val) +{ + int ret; + + asm ("bsrl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" + : "=r"(ret) : "r"(val)); + return ret + 1; +} + +#elif defined(WIN32) && !defined(_WIN64) +static inline int spice_bit_find_msb(uint32_t val) +{ + uint32_t r; + __asm { + bsr eax, val + jnz found + mov eax, -1 + +found: + mov r, eax + } + return r + 1; +} + +#else +static inline int spice_bit_find_msb(unsigned int val) +{ + signed char index = 31; + + if(val == 0) { + return 0; + } + + do { + if(val & 0x80000000) { + break; + } + val <<= 1; + } while(--index >= 0); + + return index+1; +} + +#endif + +static inline int spice_bit_next_pow2(unsigned int val) +{ + if ((val & (val - 1)) == 0) { + return val; + } + return 1 << spice_bit_find_msb(val); +} + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/canvas_base.c b/spice-common/common/canvas_base.c new file mode 100644 index 0000000..3f9e055 --- /dev/null +++ b/spice-common/common/canvas_base.c @@ -0,0 +1,3582 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef USE_LZ4 +#ifndef WIN32 +#include +#endif +#include +#endif +#include +#include "log.h" +#include "quic.h" +#include "lz.h" +#include "canvas_base.h" +#include "pixman_utils.h" +#include "canvas_utils.h" +#include "rect.h" +#include "lines.h" +#include "rop3.h" +#include "mem.h" +#include "macros.h" + +#define ROUND(_x) ((int)floor((_x) + 0.5)) + + static inline int fix_to_int(SPICE_FIXED28_4 fixed) +{ + int val, rem; + + rem = fixed & 0x0f; + val = fixed >> 4; + if (rem > 8) { + val++; + } + return val; +} + + static inline SPICE_FIXED28_4 int_to_fix(int v) +{ + return v << 4; +} + +static inline double fix_to_double(SPICE_FIXED28_4 fixed) +{ + return (double)(fixed & 0x0f) / 0x0f + (fixed >> 4); +} + +static inline uint16_t rgb_32_to_16_555(uint32_t color) +{ + return + (((color) >> 3) & 0x001f) | + (((color) >> 6) & 0x03e0) | + (((color) >> 9) & 0x7c00); +} +static inline uint16_t rgb_32_to_16_565(uint32_t color) +{ + return + (((color) >> 3) & 0x001f) | + (((color) >> 5) & 0x07e0) | + (((color) >> 8) & 0xf800); +} + +static inline uint32_t canvas_16bpp_to_32bpp(uint32_t color) +{ + uint32_t ret; + + ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2); + ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1); + ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4); + + return ret; +} +#if defined(WIN32) && defined(GDI_CANVAS) +static HDC create_compatible_dc() +{ + HDC dc = CreateCompatibleDC(NULL); + + spice_return_val_if_fail(dc != NULL, NULL); + + return dc; +} + +#endif + +typedef struct LzData { + LzUsrContext usr; + LzContext *lz; + LzDecodeUsrData decode_data; + jmp_buf jmp_env; + char message_buf[512]; +} LzData; + +typedef struct GlzData { + SpiceGlzDecoder *decoder; + LzDecodeUsrData decode_data; +} GlzData; + +typedef struct QuicData { + QuicUsrContext usr; + QuicContext *quic; + jmp_buf jmp_env; + char message_buf[512]; + SpiceChunks *chunks; + uint32_t current_chunk; +} QuicData; + +typedef struct CanvasBase { + SpiceCanvas parent; + uint32_t color_shift; + uint32_t color_mask; + QuicData quic_data; + + uint32_t format; + int width; + int height; + pixman_region32_t canvas_region; + + SpiceImageCache *bits_cache; +#ifdef SW_CANVAS_CACHE + SpicePaletteCache *palette_cache; +#endif +#ifdef WIN32 + HDC dc; +#endif + + SpiceImageSurfaces *surfaces; + + LzData lz_data; + GlzData glz_data; + SpiceJpegDecoder* jpeg; + SpiceZlibDecoder* zlib; + + void *usr_data; + spice_destroy_fn_t usr_data_destroy; +} CanvasBase; + +typedef enum { + ROP_INPUT_SRC, + ROP_INPUT_BRUSH, + ROP_INPUT_DEST +} ROPInput; + +static SpiceROP ropd_descriptor_to_rop(int desc, + ROPInput src_input, + ROPInput dest_input) +{ + int old; + int invert_masks[] = { + SPICE_ROPD_INVERS_SRC, + SPICE_ROPD_INVERS_BRUSH, + SPICE_ROPD_INVERS_DEST + }; + + old = desc; + + desc &= ~(SPICE_ROPD_INVERS_SRC | SPICE_ROPD_INVERS_DEST); + if (old & invert_masks[src_input]) { + desc |= SPICE_ROPD_INVERS_SRC; + } + + if (old & invert_masks[dest_input]) { + desc |= SPICE_ROPD_INVERS_DEST; + } + + if (desc & SPICE_ROPD_OP_PUT) { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_RES) { + return SPICE_ROP_COPY; + } + return SPICE_ROP_COPY_INVERTED; + } else { + if (desc & SPICE_ROPD_INVERS_RES) { + return SPICE_ROP_COPY_INVERTED; + } + return SPICE_ROP_COPY; + } + } else if (desc & SPICE_ROPD_OP_OR) { + + if (desc & SPICE_ROPD_INVERS_RES) { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(!src or !dest) == src and dest*/ + return SPICE_ROP_AND; + } else { + /* ! (!src or dest) = src and !dest*/ + return SPICE_ROP_AND_REVERSE; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(src or !dest) == !src and dest */ + return SPICE_ROP_AND_INVERTED; + } else { + /* !(src or dest) */ + return SPICE_ROP_NOR; + } + } + } else { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !src or !dest == !(src and dest)*/ + return SPICE_ROP_NAND; + } else { + /* !src or dest */ + return SPICE_ROP_OR_INVERTED; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* src or !dest */ + return SPICE_ROP_OR_REVERSE; + } else { + /* src or dest */ + return SPICE_ROP_OR; + } + } + } + + } else if (desc & SPICE_ROPD_OP_AND) { + + if (desc & SPICE_ROPD_INVERS_RES) { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(!src and !dest) == src or dest*/ + return SPICE_ROP_OR; + } else { + /* ! (!src and dest) = src or !dest*/ + return SPICE_ROP_OR_REVERSE; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(src and !dest) == !src or dest */ + return SPICE_ROP_OR_INVERTED; + } else { + /* !(src and dest) */ + return SPICE_ROP_NAND; + } + } + } else { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !src and !dest == !(src or dest)*/ + return SPICE_ROP_NOR; + } else { + /* !src and dest */ + return SPICE_ROP_AND_INVERTED; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* src and !dest */ + return SPICE_ROP_AND_REVERSE; + } else { + /* src and dest */ + return SPICE_ROP_AND; + } + } + } + + } else if (desc & SPICE_ROPD_OP_XOR) { + + if (desc & SPICE_ROPD_INVERS_RES) { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(!src xor !dest) == !src xor dest */ + return SPICE_ROP_EQUIV; + } else { + /* ! (!src xor dest) = src xor dest*/ + return SPICE_ROP_XOR; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !(src xor !dest) == src xor dest */ + return SPICE_ROP_XOR; + } else { + /* !(src xor dest) */ + return SPICE_ROP_EQUIV; + } + } + } else { + if (desc & SPICE_ROPD_INVERS_SRC) { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* !src xor !dest == src xor dest */ + return SPICE_ROP_XOR; + } else { + /* !src xor dest */ + return SPICE_ROP_EQUIV; + } + } else { + if (desc & SPICE_ROPD_INVERS_DEST) { + /* src xor !dest */ + return SPICE_ROP_EQUIV; + } else { + /* src xor dest */ + return SPICE_ROP_XOR; + } + } + } + + } else if (desc & SPICE_ROPD_OP_BLACKNESS) { + return SPICE_ROP_CLEAR; + } else if (desc & SPICE_ROPD_OP_WHITENESS) { + return SPICE_ROP_SET; + } else if (desc & SPICE_ROPD_OP_INVERS) { + return SPICE_ROP_INVERT; + } + return SPICE_ROP_COPY; +} + +//#define DEBUG_DUMP_COMPRESS +#ifdef DEBUG_DUMP_COMPRESS +static void dump_surface(pixman_image_t *surface, int cache); +#endif + + +static pixman_format_code_t canvas_get_target_format(CanvasBase *canvas, + int source_has_alpha) +{ + pixman_format_code_t format; + + /* Convert to target surface format */ + format = spice_surface_format_to_pixman (canvas->format); + + if (source_has_alpha) { + /* Even though the destination has no alpha, we make the source + * remember there are alpha bits instead of throwing away this + * information. The results are the same if alpha is not + * interpreted, and if need to interpret alpha, don't use + * conversion to target format. + * This is needed for instance when doing the final + * canvas_get_target_format() in canvas_get_image_internal + * as otherwise we wouldn't know if the bitmap source + * really had alpha. + */ + if (format == PIXMAN_x8r8g8b8) { + format = PIXMAN_a8r8g8b8; + } + } else { /* !source_has_alpha */ + /* If the source doesn't have alpha, but the destination has, + don't convert to alpha, since that would just do an unnecessary + copy to fill the alpha bytes with 0xff which is not expected if + we just use the raw bits, (and handled implicitly by pixman if + we're interpreting data) */ + if (format == PIXMAN_a8r8g8b8) { + format = PIXMAN_x8r8g8b8; + } + } + + return format; +} + +static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceImage *image, + int want_original) +{ + pixman_image_t *surface = NULL; + QuicData *quic_data = &canvas->quic_data; + QuicImageType type, as_type; + pixman_format_code_t pixman_format; + uint8_t *dest; + int stride; + int width; + int height; + + if (setjmp(quic_data->jmp_env)) { + pixman_image_unref(surface); + spice_warning("%s", quic_data->message_buf); + return NULL; + } + + quic_data->chunks = image->u.quic.data; + quic_data->current_chunk = 0; + + if (quic_decode_begin(quic_data->quic, + (uint32_t *)image->u.quic.data->chunk[0].data, + image->u.quic.data->chunk[0].len >> 2, + &type, &width, &height) == QUIC_ERROR) { + spice_warning("quic decode begin failed"); + return NULL; + } + + switch (type) { + case QUIC_IMAGE_TYPE_RGBA: + as_type = QUIC_IMAGE_TYPE_RGBA; + pixman_format = PIXMAN_LE_a8r8g8b8; + break; + case QUIC_IMAGE_TYPE_RGB32: + case QUIC_IMAGE_TYPE_RGB24: + as_type = QUIC_IMAGE_TYPE_RGB32; + pixman_format = PIXMAN_LE_x8r8g8b8; + break; + case QUIC_IMAGE_TYPE_RGB16: + if (!want_original && + (canvas->format == SPICE_SURFACE_FMT_32_xRGB || + canvas->format == SPICE_SURFACE_FMT_32_ARGB)) { + as_type = QUIC_IMAGE_TYPE_RGB32; + pixman_format = PIXMAN_LE_x8r8g8b8; + } else { + as_type = QUIC_IMAGE_TYPE_RGB16; + pixman_format = PIXMAN_x1r5g5b5; + } + break; + case QUIC_IMAGE_TYPE_INVALID: + case QUIC_IMAGE_TYPE_GRAY: + default: + spice_warn_if_reached(); + return NULL; + } + + spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL); + spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL); + + surface = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + pixman_format, + width, height, FALSE); + + spice_return_val_if_fail(surface != NULL, NULL); + + dest = (uint8_t *)pixman_image_get_data(surface); + stride = pixman_image_get_stride(surface); + if (quic_decode(quic_data->quic, as_type, + dest, stride) == QUIC_ERROR) { + pixman_image_unref(surface); + spice_warning("quic decode failed"); + return NULL; + } + +#ifdef DEBUG_DUMP_COMPRESS + dump_surface(surface, 0); +#endif + return surface; +} + + +//#define DUMP_JPEG +#ifdef DUMP_JPEG +static int jpeg_id = 0; +static void dump_jpeg(uint8_t* data, int data_size) +{ + char file_str[200]; + uint32_t id = ++jpeg_id; + +#ifdef WIN32 + sprintf(file_str, "c:\\tmp\\spice_dump\\%u.jpg", id); +#else + sprintf(file_str, "/tmp/spice_dump/%u.jpg", id); +#endif + + FILE *f = fopen(file_str, "wb"); + if (!f) { + return; + } + + fwrite(data, 1, data_size, f); + fclose(f); +} +#endif + +static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceImage *image) +{ + pixman_image_t *surface = NULL; + int stride; + int width; + int height; + uint8_t *dest; + + spice_return_val_if_fail(image->u.jpeg.data->num_chunks == 1, NULL); + canvas->jpeg->ops->begin_decode(canvas->jpeg, image->u.jpeg.data->chunk[0].data, image->u.jpeg.data->chunk[0].len, + &width, &height); + spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL); + spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL); + + surface = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + PIXMAN_LE_x8r8g8b8, + width, height, FALSE); + if (surface == NULL) { + spice_warning("create surface failed"); + return NULL; + } + + dest = (uint8_t *)pixman_image_get_data(surface); + stride = pixman_image_get_stride(surface); + + canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); + +#ifdef DUMP_JPEG + dump_jpeg(image->u.jpeg.data, image->u.jpeg.data_size); +#endif + return surface; +} + +#if defined(USE_LZ4) || defined(SW_CANVAS_CACHE) +static void canvas_fix_alignment(uint8_t *bits, + int stride_encoded, int stride_pixman, + int height) +{ + if (stride_pixman > stride_encoded) { + // Fix the row alignment + int row; + uint8_t *dest = bits; + for (row = height - 1; row > 0; --row) { + uint32_t *dest_aligned, *dest_misaligned; + dest_aligned = (uint32_t *)(dest + stride_pixman*row); + dest_misaligned = (uint32_t*)(dest + stride_encoded*row); + memmove(dest_aligned, dest_misaligned, stride_encoded); + } + } +} +#endif + +#ifdef USE_LZ4 +static pixman_image_t *canvas_get_lz4(CanvasBase *canvas, SpiceImage *image) +{ + pixman_image_t *surface = NULL; + int dec_size, enc_size, available; + int stride, stride_abs, stride_encoded; + uint8_t *dest, *data, *data_end, *bits; + int width, height, top_down; + LZ4_streamDecode_t *stream; + uint8_t spice_format; + pixman_format_code_t format; + + spice_chunks_linearize(image->u.lz4.data); + data = image->u.lz4.data->chunk[0].data; + data_end = data + image->u.lz4.data->chunk[0].len; + width = image->descriptor.width; + stride_encoded = width; + height = image->descriptor.height; + top_down = *(data++); + spice_format = *(data++); + switch (spice_format) { + case SPICE_BITMAP_FMT_16BIT: + format = PIXMAN_x1r5g5b5; + stride_encoded *= 2; + break; + case SPICE_BITMAP_FMT_24BIT: + format = PIXMAN_LE_r8g8b8; + stride_encoded *= 3; + break; + case SPICE_BITMAP_FMT_32BIT: + format = PIXMAN_LE_x8r8g8b8; + stride_encoded *= 4; + break; + case SPICE_BITMAP_FMT_RGBA: + format = PIXMAN_LE_a8r8g8b8; + stride_encoded *= 4; + break; + default: + spice_warning("Unsupported bitmap format %d with LZ4\n", spice_format); + return NULL; + } + + surface = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + format, + width, height, top_down); + if (surface == NULL) { + spice_warning("create surface failed"); + return NULL; + } + + stream = LZ4_createStreamDecode(); + dest = (uint8_t *)pixman_image_get_data(surface); + stride = pixman_image_get_stride(surface); + stride_abs = abs(stride); + available = height * stride_abs; + if (!top_down) { + dest -= (stride_abs * (height - 1)); + } + bits = dest; + + do { + // Read next compressed block + enc_size = ntohl(*((uint32_t *)data)); + data += 4; + dec_size = LZ4_decompress_safe_continue(stream, (const char *) data, + (char *) dest, enc_size, available); + if (dec_size <= 0) { + spice_warning("Error decoding LZ4 block\n"); + pixman_image_unref(surface); + surface = NULL; + break; + } + dest += dec_size; + available -= dec_size; + data += enc_size; + } while (data < data_end); + + canvas_fix_alignment(bits, stride_encoded, stride_abs, height); + + LZ4_freeStreamDecode(stream); + return surface; +} +#endif + +static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, SpiceImage *image) +{ + pixman_image_t *surface = NULL; + int stride; + int width; + int height; + uint8_t *dest; + int alpha_top_down = FALSE; + LzData *lz_data = &canvas->lz_data; + LzImageType lz_alpha_type; + uint8_t *comp_alpha_buf = NULL; + uint8_t *decomp_alpha_buf = NULL; + int alpha_size; + int lz_alpha_width, lz_alpha_height, n_comp_pixels, lz_alpha_top_down; + + spice_return_val_if_fail(image->u.jpeg_alpha.data->num_chunks == 1, NULL); + canvas->jpeg->ops->begin_decode(canvas->jpeg, + image->u.jpeg_alpha.data->chunk[0].data, + image->u.jpeg_alpha.jpeg_size, + &width, &height); + spice_return_val_if_fail((uint32_t)width == image->descriptor.width, NULL); + spice_return_val_if_fail((uint32_t)height == image->descriptor.height, NULL); + + if (image->u.jpeg_alpha.flags & SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN) { + alpha_top_down = TRUE; + } + +#ifdef WIN32 + lz_data->decode_data.dc = canvas->dc; +#endif + surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_LE_a8r8g8b8, + width, height, width*height, alpha_top_down); + + if (surface == NULL) { + spice_warning("create surface failed"); + return NULL; + } + + dest = (uint8_t *)pixman_image_get_data(surface); + stride = pixman_image_get_stride(surface); + + canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); + + comp_alpha_buf = image->u.jpeg_alpha.data->chunk[0].data + image->u.jpeg_alpha.jpeg_size; + alpha_size = image->u.jpeg_alpha.data_size - image->u.jpeg_alpha.jpeg_size; + + lz_decode_begin(lz_data->lz, comp_alpha_buf, alpha_size, &lz_alpha_type, + &lz_alpha_width, &lz_alpha_height, &n_comp_pixels, + &lz_alpha_top_down, NULL); + spice_return_val_if_fail(lz_alpha_type == LZ_IMAGE_TYPE_XXXA, NULL); + spice_return_val_if_fail(!!lz_alpha_top_down == !!alpha_top_down, NULL); + spice_return_val_if_fail(lz_alpha_width == width, NULL); + spice_return_val_if_fail(lz_alpha_height == height, NULL); + spice_return_val_if_fail(n_comp_pixels == width * height, NULL); + + if (!alpha_top_down) { + decomp_alpha_buf = dest + stride * (height - 1); + } else { + decomp_alpha_buf = dest; + } + lz_decode(lz_data->lz, LZ_IMAGE_TYPE_XXXA, decomp_alpha_buf); + +#ifdef DUMP_JPEG + dump_jpeg(image->u.jpeg_alpha.data, image->u.jpeg_alpha.jpeg_size); +#endif + return surface; +} + +static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* bitmap, + SpicePalette *palette, int want_original) +{ + uint8_t* src; + pixman_image_t *image; + pixman_format_code_t format; + + spice_chunks_linearize(bitmap->data); + + src = bitmap->data->chunk[0].data; + + if (want_original) { + format = spice_bitmap_format_to_pixman(bitmap->format, canvas->format); + } else { + format = canvas_get_target_format(canvas, + bitmap->format == SPICE_BITMAP_FMT_RGBA); + } + + image = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + format, + bitmap->x, bitmap->y, FALSE); + if (image == NULL) { + spice_warning("create surface failed"); + return NULL; + } + + spice_bitmap_convert_to_pixman(format, image, + bitmap->format, + bitmap->flags, + bitmap->x, bitmap->y, + src, bitmap->stride, + canvas->format, palette); + return image; +} + + +#ifdef SW_CANVAS_CACHE + +static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags) +{ + SpicePalette *palette; + + if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) { + palette = canvas->palette_cache->ops->get(canvas->palette_cache, palette_id); + } else { + palette = base_palette; + if (palette != NULL && flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) { + canvas->palette_cache->ops->put(canvas->palette_cache, palette); + } + } + return palette; +} + +static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags, int *free_palette) +{ + SpicePalette *palette = canvas_get_palette(canvas, base_palette, palette_id, flags); + SpicePalette *copy; + uint32_t *now, *end; + size_t size; + + if (canvas->format == SPICE_SURFACE_FMT_32_xRGB || + canvas->format == SPICE_SURFACE_FMT_32_ARGB) { + return palette; + } + + size = sizeof(SpicePalette) + palette->num_ents * 4; + copy = (SpicePalette *)spice_malloc(size); + memcpy(copy, palette, size); + + switch (canvas->format) { + case SPICE_SURFACE_FMT_32_xRGB: + case SPICE_SURFACE_FMT_32_ARGB: + /* Won't happen */ + break; + case SPICE_SURFACE_FMT_16_555: + now = copy->ents; + end = now + copy->num_ents; + for (; now < end; now++) { + *now = canvas_16bpp_to_32bpp(*now); + } + break; + case SPICE_SURFACE_FMT_16_565: + default: + spice_warn_if_reached(); + free(copy); + return NULL; + } + *free_palette = TRUE; + return copy; +} + +static pixman_image_t *canvas_get_lz(CanvasBase *canvas, SpiceImage *image, + int want_original) +{ + LzData *lz_data = &canvas->lz_data; + uint8_t *comp_buf = NULL; + int comp_size; + uint8_t *decomp_buf = NULL; + pixman_format_code_t pixman_format; + LzImageType type, as_type; + SpicePalette *palette; + int n_comp_pixels; + int width; + int height; + int top_down; + int stride_encoded; + int stride; + int free_palette; + + if (setjmp(lz_data->jmp_env)) { + free(decomp_buf); + spice_warning("%s", lz_data->message_buf); + return NULL; + } + + free_palette = FALSE; + if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) { + spice_return_val_if_fail(image->u.lz_rgb.data->num_chunks == 1, NULL); /* TODO: Handle chunks */ + comp_buf = image->u.lz_rgb.data->chunk[0].data; + comp_size = image->u.lz_rgb.data->chunk[0].len; + palette = NULL; + } else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { + spice_return_val_if_fail(image->u.lz_plt.data->num_chunks == 1, NULL); /* TODO: Handle chunks */ + comp_buf = image->u.lz_plt.data->chunk[0].data; + comp_size = image->u.lz_plt.data->chunk[0].len; + palette = canvas_get_localized_palette(canvas, image->u.lz_plt.palette, image->u.lz_plt.palette_id, image->u.lz_plt.flags, &free_palette); + } else { + spice_warn_if_reached(); + return NULL; + } + + lz_decode_begin(lz_data->lz, comp_buf, comp_size, &type, + &width, &height, &n_comp_pixels, &top_down, palette); + + stride_encoded = width; + switch (type) { + case LZ_IMAGE_TYPE_RGBA: + as_type = LZ_IMAGE_TYPE_RGBA; + pixman_format = PIXMAN_LE_a8r8g8b8; + stride_encoded *= 4; + break; + case LZ_IMAGE_TYPE_RGB32: + case LZ_IMAGE_TYPE_RGB24: + case LZ_IMAGE_TYPE_PLT1_LE: + case LZ_IMAGE_TYPE_PLT1_BE: + case LZ_IMAGE_TYPE_PLT4_LE: + case LZ_IMAGE_TYPE_PLT4_BE: + case LZ_IMAGE_TYPE_PLT8: + as_type = LZ_IMAGE_TYPE_RGB32; + pixman_format = PIXMAN_LE_x8r8g8b8; + stride_encoded *= 4; + break; + case LZ_IMAGE_TYPE_A8: + as_type = LZ_IMAGE_TYPE_A8; + pixman_format = PIXMAN_a8; + break; + case LZ_IMAGE_TYPE_RGB16: + if (!want_original && + (canvas->format == SPICE_SURFACE_FMT_32_xRGB || + canvas->format == SPICE_SURFACE_FMT_32_ARGB)) { + as_type = LZ_IMAGE_TYPE_RGB32; + pixman_format = PIXMAN_LE_x8r8g8b8; + stride_encoded *= 4; + } else { + as_type = LZ_IMAGE_TYPE_RGB16; + pixman_format = PIXMAN_x1r5g5b5; + stride_encoded *= 2; + } + break; + default: + spice_warn_if_reached(); + return NULL; + } + + spice_return_val_if_fail((unsigned)width == image->descriptor.width, NULL); + spice_return_val_if_fail((unsigned)height == image->descriptor.height, NULL); + + spice_return_val_if_fail((image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) || (n_comp_pixels == width * height), NULL); +#ifdef WIN32 + lz_data->decode_data.dc = canvas->dc; +#endif + + + alloc_lz_image_surface(&lz_data->decode_data, pixman_format, + width, height, n_comp_pixels, top_down); + + stride = pixman_image_get_stride(lz_data->decode_data.out_surface); + stride = abs(stride); + + decomp_buf = (uint8_t *)pixman_image_get_data(lz_data->decode_data.out_surface); + if (!top_down) { + decomp_buf -= stride * (height - 1); + } + + lz_decode(lz_data->lz, as_type, decomp_buf); + + canvas_fix_alignment(decomp_buf, stride_encoded, stride, height); + + if (free_palette) { + free(palette); + } + + return lz_data->decode_data.out_surface; +} + +static pixman_image_t *canvas_get_glz_rgb_common(CanvasBase *canvas, uint8_t *data, + int want_original) +{ + spice_return_val_if_fail(canvas->glz_data.decoder != NULL, NULL); + + canvas->glz_data.decoder->ops->decode(canvas->glz_data.decoder, + data, NULL, + &canvas->glz_data.decode_data); + + /* global_decode calls alloc_lz_image, which sets canvas->glz_data.surface */ + return (canvas->glz_data.decode_data.out_surface); +} + +// don't handle plts since bitmaps with plt can be decoded globally to RGB32 (because +// same byte sequence can be transformed to different RGB pixels by different plts) +static pixman_image_t *canvas_get_glz(CanvasBase *canvas, SpiceImage *image, + int want_original) +{ + spice_return_val_if_fail(image->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB, NULL); +#ifdef WIN32 + canvas->glz_data.decode_data.dc = canvas->dc; +#endif + + spice_return_val_if_fail(image->u.lz_rgb.data->num_chunks == 1, NULL); /* TODO: Handle chunks */ + return canvas_get_glz_rgb_common(canvas, image->u.lz_rgb.data->chunk[0].data, want_original); +} + +static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceImage *image, + int want_original) +{ + uint8_t *glz_data; + pixman_image_t *surface; + + spice_return_val_if_fail(canvas->zlib != NULL, NULL); + + spice_return_val_if_fail(image->u.zlib_glz.data->num_chunks == 1, NULL); /* TODO: Handle chunks */ + glz_data = (uint8_t*)spice_malloc(image->u.zlib_glz.glz_data_size); + canvas->zlib->ops->decode(canvas->zlib, image->u.zlib_glz.data->chunk[0].data, + image->u.zlib_glz.data->chunk[0].len, + glz_data, image->u.zlib_glz.glz_data_size); + surface = canvas_get_glz_rgb_common(canvas, glz_data, want_original); + free(glz_data); + return surface; +} + +//#define DEBUG_DUMP_BITMAP + +#ifdef DEBUG_DUMP_BITMAP +static void dump_bitmap(SpiceBitmap *bitmap, SpicePalette *palette) +{ + uint8_t* data = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data); + static uint32_t file_id = 0; + uint32_t i, j; + char file_str[200]; + uint32_t id = ++file_id; + +#ifdef WIN32 + sprintf(file_str, "c:\\tmp\\spice_dump\\%u.%ubpp", id, bitmap->format); +#else + sprintf(file_str, "/tmp/spice_dump/%u.%ubpp", id, bitmap->format); +#endif + FILE *f = fopen(file_str, "wb"); + if (!f) { + return; + } + + fprintf(f, "%d\n", bitmap->format); // 1_LE,1_BE,.... + fprintf(f, "%d %d\n", bitmap->x, bitmap->y); // width and height + fprintf(f, "%d\n", palette->num_ents); // #plt entries + for (i = 0; i < palette->num_ents; i++) { + fwrite(&(palette->ents[i]), 4, 1, f); + } + fprintf(f, "\n"); + + for (i = 0; i < bitmap->y; i++, data += bitmap->stride) { + uint8_t *now = data; + for (j = 0; j < bitmap->x; j++) { + fwrite(now, 1, 1, f); + now++; + } + } +} + +#endif + +static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap, + int want_original) +{ + pixman_image_t* surface; + SpicePalette *palette; + + palette = canvas_get_palette(canvas, bitmap->palette, bitmap->palette_id, bitmap->flags); +#ifdef DEBUG_DUMP_BITMAP + if (palette) { + dump_bitmap(bitmap, palette); + } +#endif + + surface = canvas_bitmap_to_surface(canvas, bitmap, palette, want_original); + + if (palette && (bitmap->flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + canvas->palette_cache->ops->release(canvas->palette_cache, palette); + } + + return surface; +} + +#else + + +static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap, + int want_original) +{ + SpicePalette *palette; + + if (!bitmap->palette) { + return canvas_bitmap_to_surface(canvas, bitmap, NULL, want_original); + } + palette = (SpicePalette *)SPICE_GET_ADDRESS(bitmap->palette); + return canvas_bitmap_to_surface(canvas, bitmap, palette, want_original); +} + +#endif + + + +// caution: defining DEBUG_DUMP_SURFACE will dump both cached & non-cached +// images to disk. it will reduce performance dramatically & eat +// disk space rapidly. use it only for debugging. +//#define DEBUG_DUMP_SURFACE + +#if defined(DEBUG_DUMP_SURFACE) || defined(DEBUG_DUMP_COMPRESS) + +static void dump_surface(pixman_image_t *surface, int cache) +{ + static uint32_t file_id = 0; + int i, j; + char file_str[200]; + int depth = pixman_image_get_depth(surface); + + if (depth != 24 && depth != 32) { + return; + } + + uint8_t *data = (uint8_t *)pixman_image_get_data(surface); + int width = pixman_image_get_width(surface); + int height = pixman_image_get_height(surface); + int stride = pixman_image_get_stride(surface); + + uint32_t id = ++file_id; +#ifdef WIN32 + sprintf(file_str, "c:\\tmp\\spice_dump\\%d\\%u.ppm", cache, id); +#else + sprintf(file_str, "/tmp/spice_dump/%u.ppm", id); +#endif + FILE *f = fopen(file_str, "wb"); + if (!f) { + return; + } + fprintf(f, "P6\n"); + fprintf(f, "%d %d\n", width, height); + fprintf(f, "#spicec dump\n"); + fprintf(f, "255\n"); + for (i = 0; i < height; i++, data += stride) { + uint8_t *now = data; + for (j = 0; j < width; j++) { + fwrite(&now[2], 1, 1, f); + fwrite(&now[1], 1, 1, f); + fwrite(&now[0], 1, 1, f); + now += 4; + } + } + fclose(f); +} + +#endif + +static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SpiceImage *image) +{ + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + SpiceSurface *surface = &image->u.surface; + return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); + } + return NULL; +} + +static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SpiceImage *image) +{ + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + SpiceSurface *surface = &image->u.surface; + return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); + } + return NULL; +} + + +#if defined(SW_CANVAS_CACHE) +static int image_has_palette_to_cache(SpiceImage *image) +{ + SpiceImageDescriptor *descriptor = &image->descriptor; + + if (descriptor->type == SPICE_IMAGE_TYPE_BITMAP) { + return image->u.bitmap.palette && + (image->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME); + } else if (descriptor->type == SPICE_IMAGE_TYPE_LZ_PLT) { + return image->u.lz_plt.palette && + (image->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME); + } + return FALSE; +} +#endif + +//#define DEBUG_LZ + +/* If real get is FALSE, then only do whatever is needed but don't return an image. For instance, + * if we need to read it to cache it we do. + * + * This generally converts the image to the right type for the canvas. + * However, if want_original is set the real source format is returned, and + * you have to be able to handle any image format. This is useful to avoid + * e.g. losing alpha when blending a argb32 image on a rgb16 surface. + */ +static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image, + int want_original, int real_get) +{ + SpiceImageDescriptor *descriptor = &image->descriptor; + pixman_image_t *surface, *converted; + pixman_format_code_t wanted_format, surface_format; + int saved_want_original; + + /* When touching, only really allocate if we need to cache, or + * if we're loading a GLZ stream (since those need inter-thread communication + * to happen which breaks if we don't. */ + if (!real_get && + !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME) && +#ifdef SW_CANVAS_CACHE + !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) && + !image_has_palette_to_cache(image) && +#endif + (descriptor->type != SPICE_IMAGE_TYPE_GLZ_RGB) && + (descriptor->type != SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB)) { + return NULL; + } + + saved_want_original = want_original; + if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME +#ifdef SW_CANVAS_CACHE + || descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME +#endif + ) { + want_original = TRUE; + } + + switch (descriptor->type) { + case SPICE_IMAGE_TYPE_QUIC: { + surface = canvas_get_quic(canvas, image, want_original); + break; + } +#if defined(SW_CANVAS_CACHE) + case SPICE_IMAGE_TYPE_LZ_PLT: + case SPICE_IMAGE_TYPE_LZ_RGB: { + surface = canvas_get_lz(canvas, image, want_original); + break; + } +#endif + case SPICE_IMAGE_TYPE_JPEG: { + surface = canvas_get_jpeg(canvas, image); + break; + } + case SPICE_IMAGE_TYPE_JPEG_ALPHA: { + surface = canvas_get_jpeg_alpha(canvas, image); + break; + } + case SPICE_IMAGE_TYPE_LZ4: { +#ifdef USE_LZ4 + surface = canvas_get_lz4(canvas, image); +#else + spice_warning("Lz4 compression algorithm not supported.\n"); + surface = NULL; +#endif + break; + } +#if defined(SW_CANVAS_CACHE) + case SPICE_IMAGE_TYPE_GLZ_RGB: { + surface = canvas_get_glz(canvas, image, want_original); + break; + } + case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: { + surface = canvas_get_zlib_glz_rgb(canvas, image, want_original); + break; + } +#endif + case SPICE_IMAGE_TYPE_FROM_CACHE: + surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id); + break; +#ifdef SW_CANVAS_CACHE + case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: + surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, descriptor->id); + break; +#endif + case SPICE_IMAGE_TYPE_BITMAP: { + surface = canvas_get_bits(canvas, &image->u.bitmap, want_original); + break; + } + default: + spice_warn_if_reached(); + return NULL; + } + + spice_return_val_if_fail(surface != NULL, NULL); + spice_return_val_if_fail(spice_pixman_image_get_format(surface, &surface_format), NULL); + + if (descriptor->flags & SPICE_IMAGE_FLAGS_HIGH_BITS_SET && + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE && +#ifdef SW_CANVAS_CACHE + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && +#endif + surface_format == PIXMAN_x8r8g8b8) { + spice_pixman_fill_rect_rop(surface, + 0, 0, + pixman_image_get_width(surface), + pixman_image_get_height(surface), + 0xff000000U, SPICE_ROP_OR); + } + + if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME && +#ifdef SW_CANVAS_CACHE + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && +#endif + descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE ) { +#ifdef SW_CANVAS_CACHE + if (!spice_image_descriptor_is_lossy(descriptor)) { + canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); + } else { + canvas->bits_cache->ops->put_lossy(canvas->bits_cache, descriptor->id, surface); + } +#else + canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); +#endif +#ifdef DEBUG_DUMP_SURFACE + dump_surface(surface, 1); +#endif +#ifdef SW_CANVAS_CACHE + } else if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) { + if (spice_image_descriptor_is_lossy(descriptor)) { + spice_warning("invalid cache replace request: the image is lossy"); + return NULL; + } + canvas->bits_cache->ops->replace_lossy(canvas->bits_cache, descriptor->id, surface); +#ifdef DEBUG_DUMP_SURFACE + dump_surface(surface, 1); +#endif +#endif +#ifdef DEBUG_DUMP_SURFACE + } else if (descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE +#ifdef SW_CANVAS_CACHE + && descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS +#endif + ) { + + dump_surface(surface, 0); +#endif + } + + if (!real_get) { + pixman_image_unref(surface); + return NULL; + } + + if (!saved_want_original) { + /* Conversion to canvas format was requested, but maybe it didn't + happen above (due to save/load to cache for instance, or + maybe the reader didn't support conversion). + If so we convert here. */ + + wanted_format = canvas_get_target_format(canvas, +#ifdef WORDS_BIGENDIAN + surface_format == PIXMAN_b8g8r8a8 || +#endif + surface_format == PIXMAN_a8r8g8b8); + + if (surface_format != wanted_format) { + converted = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + wanted_format, + pixman_image_get_width(surface), + pixman_image_get_height(surface), + TRUE); + pixman_image_composite32 (PIXMAN_OP_SRC, + surface, NULL, converted, + 0, 0, + 0, 0, + 0, 0, + pixman_image_get_width(surface), + pixman_image_get_height(surface)); + pixman_image_unref (surface); + surface = converted; + } + } + + return surface; +} + +static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SpiceImage *image) +{ + return canvas_get_surface_mask_internal(canvas, image); +} + +static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SpiceImage *image) +{ + return canvas_get_surface_internal(canvas, image); +} + +static pixman_image_t *canvas_get_image(CanvasBase *canvas, SpiceImage *image, + int want_original) +{ + return canvas_get_image_internal(canvas, image, want_original, TRUE); +} + +static void canvas_touch_image(CanvasBase *canvas, SpiceImage *image) +{ + canvas_get_image_internal(canvas, image, TRUE, FALSE); +} + +static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas, + int x, int y, + int32_t width, int32_t height, + int force_opaque) +{ + CanvasBase *canvas_base = (CanvasBase *)canvas; + pixman_image_t *surface; + uint8_t *dest; + int dest_stride; + SpiceRect area; + pixman_format_code_t format; + + format = spice_surface_format_to_pixman (canvas_base->format); + if (force_opaque) + { + /* Set alpha bits of the format to 0 */ + format = (pixman_format_code_t)(((uint32_t)format) & ~(0xf << 12)); + + spice_return_val_if_fail ( + pixman_format_supported_destination (format), NULL); + } + + surface = pixman_image_create_bits(spice_surface_format_to_pixman (canvas_base->format), + width, height, NULL, 0); + spice_return_val_if_fail(surface != NULL, NULL); + + dest = (uint8_t *)pixman_image_get_data(surface); + dest_stride = pixman_image_get_stride(surface); + + area.left = x; + area.top = y; + area.right = x + width; + area.bottom = y + height; + + canvas->ops->read_bits(canvas, dest, dest_stride, &area); + + return surface; +} + + +#ifdef REVERS_BITS_SLOW +static inline uint8_t revers_bits(uint8_t byte) +{ + uint8_t ret = 0; + int i; + + for (i = 0; i < 4; i++) { + int shift = 7 - i * 2; + ret |= (byte & (1 << i)) << shift; + ret |= (byte & (0x80 >> i)) >> shift; + } + return ret; +} +#else +static inline uint8_t revers_bits(uint8_t byte) +{ + static const uint8_t revers[] = { + 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x8, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x4, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0xc, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x2, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0xa, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x6, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0xe, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x1, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x9, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x5, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0xd, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x3, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0xb, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x7, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0xf, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff + }; + + return revers[byte]; +} +#endif + +static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* bitmap, int invers) +{ + pixman_image_t *surface; + uint8_t *src_line; + uint8_t *end_line; + uint8_t *dest_line; + int src_stride; + int line_size; + int dest_stride; + + surface = surface_create( +#ifdef WIN32 + canvas->dc, +#endif + PIXMAN_a1, bitmap->x, bitmap->y, TRUE); + spice_return_val_if_fail(surface != NULL, NULL); + + spice_chunks_linearize(bitmap->data); + src_line = bitmap->data->chunk[0].data; + src_stride = bitmap->stride; + end_line = src_line + (bitmap->y * src_stride); + line_size = SPICE_ALIGN(bitmap->x, 8) >> 3; + + dest_stride = pixman_image_get_stride(surface); + dest_line = (uint8_t *)pixman_image_get_data(surface); + if (!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + spice_return_val_if_fail(bitmap->y > 0, NULL); + dest_line += dest_stride * ((int)bitmap->y - 1); + dest_stride = -dest_stride; + } + + if (invers) { + switch (bitmap->format) { +#if defined(GDI_CANVAS) + case SPICE_BITMAP_FMT_1BIT_BE: +#else + case SPICE_BITMAP_FMT_1BIT_LE: +#endif + for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { + uint8_t *dest = dest_line; + uint8_t *now = src_line; + uint8_t *end = now + line_size; + while (now < end) { + *(dest++) = ~*(now++); + } + } + break; +#if defined(GDI_CANVAS) + case SPICE_BITMAP_FMT_1BIT_LE: +#else + case SPICE_BITMAP_FMT_1BIT_BE: +#endif + for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { + uint8_t *dest = dest_line; + uint8_t *now = src_line; + uint8_t *end = now + line_size; + + while (now < end) { + *(dest++) = ~revers_bits(*(now++)); + } + } + break; + default: + pixman_image_unref(surface); + surface = NULL; + spice_warn_if_reached(); + return NULL; + } + } else { + switch (bitmap->format) { +#if defined(GDI_CANVAS) + case SPICE_BITMAP_FMT_1BIT_BE: +#else + case SPICE_BITMAP_FMT_1BIT_LE: +#endif + for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { + memcpy(dest_line, src_line, line_size); + } + break; +#if defined(GDI_CANVAS) + case SPICE_BITMAP_FMT_1BIT_LE: +#else + case SPICE_BITMAP_FMT_1BIT_BE: +#endif + for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { + uint8_t *dest = dest_line; + uint8_t *now = src_line; + uint8_t *end = now + line_size; + + while (now < end) { + *(dest++) = revers_bits(*(now++)); + } + } + break; + default: + pixman_image_unref(surface); + surface = NULL; + spice_warn_if_reached(); + return NULL; + } + } + return surface; +} + +static inline pixman_image_t *canvas_A1_invers(pixman_image_t *src_surf) +{ + int width = pixman_image_get_width(src_surf); + int height = pixman_image_get_height(src_surf); + pixman_image_t * invers; + uint8_t *src_line, *end_line, *dest_line; + int src_stride, line_size, dest_stride; + + spice_return_val_if_fail(pixman_image_get_depth(src_surf) == 1, NULL); + + invers = pixman_image_create_bits(PIXMAN_a1, width, height, NULL, 0); + spice_return_val_if_fail(invers != NULL, NULL); + + src_line = (uint8_t *)pixman_image_get_data(src_surf); + src_stride = pixman_image_get_stride(src_surf); + end_line = src_line + (height * src_stride); + line_size = SPICE_ALIGN(width, 8) >> 3; + dest_line = (uint8_t *)pixman_image_get_data(invers); + dest_stride = pixman_image_get_stride(invers); + + for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { + uint8_t *dest = dest_line; + uint8_t *now = src_line; + uint8_t *end = now + line_size; + while (now < end) { + *(dest++) = ~*(now++); + } + } + return invers; +} + +static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out) +{ + SpiceImage *image; + pixman_image_t *surface; + int need_invers; + int is_invers; + int cache_me; + + if (needs_invert_out) { + *needs_invert_out = 0; + } + + image = mask->bitmap; + need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS; + +#ifdef SW_CANVAS_CACHE + cache_me = image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME; +#else + cache_me = 0; +#endif + + switch (image->descriptor.type) { + case SPICE_IMAGE_TYPE_BITMAP: { + is_invers = need_invers && !cache_me; + surface = canvas_get_bitmap_mask(canvas, &image->u.bitmap, is_invers); + break; + } + case SPICE_IMAGE_TYPE_FROM_CACHE: + surface = canvas->bits_cache->ops->get(canvas->bits_cache, image->descriptor.id); + is_invers = 0; + break; +#ifdef SW_CANVAS_CACHE + case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: + surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, image->descriptor.id); + is_invers = 0; + break; +#endif + default: + spice_warn_if_reached(); + return NULL; + } + + if (cache_me) { + canvas->bits_cache->ops->put(canvas->bits_cache, image->descriptor.id, surface); + } + + if (need_invers && !is_invers) { // surface is in cache + if (needs_invert_out != NULL) { + *needs_invert_out = TRUE; + } else { + pixman_image_t *inv_surf; + inv_surf = canvas_A1_invers(surface); + pixman_image_unref(surface); + surface = inv_surf; + } + } + + return surface; +} + +static inline void canvas_raster_glyph_box(const SpiceRasterGlyph *glyph, SpiceRect *r) +{ + spice_return_if_fail(r != NULL); + + r->top = glyph->render_pos.y + glyph->glyph_origin.y; + r->bottom = r->top + glyph->height; + r->left = glyph->render_pos.x + glyph->glyph_origin.x; + r->right = r->left + glyph->width; +} + +static inline void __canvas_put_bits(uint8_t *dest, int offset, uint8_t val, int n) +{ + uint8_t mask; + int now; + + dest = dest + (offset >> 3); + offset &= 0x07; + + now = MIN(8 - offset, n); + + mask = (1 << now) - 1; + mask <<= offset; + val = revers_bits(val); + *dest = ((val << offset) & mask) | *dest; + + if ((n = n - now)) { + mask = (1 << n) - 1; + dest++; + *dest = ((val >> now) & mask) | *dest; + } +} + +static inline void canvas_put_bits(uint8_t *dest, int dest_offset, uint8_t *src, int n) +{ + while (n) { + int now = MIN(n, 8); + + n -= now; + __canvas_put_bits(dest, dest_offset, *src, now); + dest_offset += now; + src++; + } +} + +static void canvas_put_glyph_bits(SpiceRasterGlyph *glyph, int bpp, uint8_t *dest, int dest_stride, + SpiceRect *bounds) +{ + SpiceRect glyph_box; + uint8_t *src; + int lines; + int width; + + //todo: support SPICE_STRING_FLAGS_RASTER_TOP_DOWN + canvas_raster_glyph_box(glyph, &glyph_box); + spice_return_if_fail(glyph_box.top >= bounds->top && glyph_box.bottom <= bounds->bottom); + spice_return_if_fail(glyph_box.left >= bounds->left && glyph_box.right <= bounds->right); + rect_offset(&glyph_box, -bounds->left, -bounds->top); + + dest += glyph_box.top * dest_stride; + src = glyph->data; + lines = glyph_box.bottom - glyph_box.top; + width = glyph_box.right - glyph_box.left; + switch (bpp) { + case 1: { + int src_stride = SPICE_ALIGN(width, 8) >> 3; + int i; + + src += src_stride * (lines); + for (i = 0; i < lines; i++) { + src -= src_stride; + canvas_put_bits(dest, glyph_box.left, src, width); + dest += dest_stride; + } + break; + } + case 4: { + uint8_t *end; + int src_stride = SPICE_ALIGN(width * 4, 8) >> 3; + + src += src_stride * lines; + dest += glyph_box.left; + end = dest + dest_stride * lines; + for (; dest != end; dest += dest_stride) { + int i = 0; + uint8_t *now; + + src -= src_stride; + now = src; + while (i < (width & ~1)) { + dest[i] = MAX(dest[i], *now & 0xf0); + dest[i + 1] = MAX(dest[i + 1], *now << 4); + i += 2; + now++; + } + if (i < width) { + dest[i] = MAX(dest[i], *now & 0xf0); + now++; + } + } + break; + } + case 8: { + uint8_t *end; + src += width * lines; + dest += glyph_box.left; + end = dest + dest_stride * lines; + for (; dest != end; dest += dest_stride, src -= width) { + int i; + + for (i = 0; i < width; i++) { + dest[i] = MAX(dest[i], src[i]); + } + } + break; + } + default: + spice_warn_if_reached(); + return; + } +} + +static pixman_image_t *canvas_get_str_mask(CanvasBase *canvas, SpiceString *str, int bpp, SpicePoint *pos) +{ + SpiceRasterGlyph *glyph; + SpiceRect bounds; + pixman_image_t *str_mask; + uint8_t *dest; + int dest_stride; + int i; + + spice_return_val_if_fail(str->length > 0, NULL); + + glyph = str->glyphs[0]; + canvas_raster_glyph_box(glyph, &bounds); + + for (i = 1; i < str->length; i++) { + SpiceRect glyph_box; + + canvas_raster_glyph_box(str->glyphs[i], &glyph_box); + rect_union(&bounds, &glyph_box); + } + + str_mask = pixman_image_create_bits((bpp == 1) ? PIXMAN_a1 : PIXMAN_a8, + bounds.right - bounds.left, + bounds.bottom - bounds.top, NULL, 0); + spice_return_val_if_fail(str_mask != NULL, NULL); + + dest = (uint8_t *)pixman_image_get_data(str_mask); + dest_stride = pixman_image_get_stride(str_mask); + for (i = 0; i < str->length; i++) { + glyph = str->glyphs[i]; + canvas_put_glyph_bits(glyph, bpp, dest, dest_stride, &bounds); + } + + pos->x = bounds.left; + pos->y = bounds.top; + return str_mask; +} + +static pixman_image_t *canvas_scale_surface(pixman_image_t *src, const SpiceRect *src_area, int width, + int height, int scale_mode) +{ + pixman_image_t *surface; + pixman_transform_t transform; + pixman_format_code_t format; + double sx, sy; + + spice_return_val_if_fail(spice_pixman_image_get_format (src, &format), NULL); + + surface = pixman_image_create_bits(format, width, height, NULL, 0); + spice_return_val_if_fail(surface != NULL, NULL); + + sx = (double)(src_area->right - src_area->left) / width; + sy = (double)(src_area->bottom - src_area->top) / height; + + pixman_transform_init_scale(&transform, pixman_double_to_fixed(sx), pixman_double_to_fixed(sy)); + + pixman_image_set_transform (src, &transform); + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + spice_return_val_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST, NULL); + pixman_image_set_filter(src, + (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, + NULL, 0); + + pixman_image_composite32(PIXMAN_OP_SRC, + src, NULL, surface, + ROUND(src_area->left / sx), ROUND (src_area->top / sy), + 0, 0, /* mask */ + 0, 0, /* dst */ + width, height); + + pixman_transform_init_identity(&transform); + pixman_image_set_transform(src, &transform); + + return surface; +} + +SPICE_ATTR_NORETURN +SPICE_ATTR_PRINTF(2, 3) static void quic_usr_error(QuicUsrContext *usr, const char *fmt, ...) +{ + QuicData *usr_data = (QuicData *)usr; + va_list ap; + + va_start(ap, fmt); + vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); + va_end(ap); + + longjmp(usr_data->jmp_env, 1); +} + +SPICE_ATTR_PRINTF(2, 3) static void quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...) +{ + QuicData *usr_data = (QuicData *)usr; + va_list ap; + + va_start(ap, fmt); + vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); + va_end(ap); +} + +static void *quic_usr_malloc(QuicUsrContext *usr, int size) +{ + return spice_malloc(size); +} + +static void quic_usr_free(QuicUsrContext *usr, void *ptr) +{ + free(ptr); +} + +SPICE_ATTR_PRINTF(2, 3) static void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...) +{ + LzData *usr_data = (LzData *)usr; + va_list ap; + + va_start(ap, fmt); + vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); + va_end(ap); +} + +SPICE_ATTR_NORETURN +SPICE_ATTR_PRINTF(2, 3) static void lz_usr_error(LzUsrContext *usr, const char *fmt, ...) +{ + LzData *usr_data = (LzData *)usr; + va_list ap; + + va_start(ap, fmt); + vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); + va_end(ap); + + longjmp(usr_data->jmp_env, 1); +} + +static void *lz_usr_malloc(LzUsrContext *usr, int size) +{ + return spice_malloc(size); +} + +static void lz_usr_free(LzUsrContext *usr, void *ptr) +{ + free(ptr); +} + +static int lz_usr_more_space(LzUsrContext *usr, uint8_t **io_ptr) +{ + return 0; +} + +static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines) +{ + return 0; +} + +static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed) +{ + QuicData *quic_data = (QuicData *)usr; + + if (quic_data->current_chunk == quic_data->chunks->num_chunks -1) { + return 0; + } + quic_data->current_chunk++; + + *io_ptr = (uint32_t *)quic_data->chunks->chunk[quic_data->current_chunk].data; + return quic_data->chunks->chunk[quic_data->current_chunk].len >> 2; +} + + +static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) +{ + return 0; +} + +static void canvas_base_destroy(CanvasBase *canvas) +{ + quic_destroy(canvas->quic_data.quic); + lz_destroy(canvas->lz_data.lz); +#ifdef GDI_CANVAS + DeleteDC(canvas->dc); +#endif + + if (canvas->usr_data && canvas->usr_data_destroy) { + canvas->usr_data_destroy (canvas->usr_data); + canvas->usr_data = NULL; + } +} + +/* This is kind of lame, but it protects against multiple + instances of these functions. We really should stop including + canvas_base.c and build it separately instead */ +#ifdef CANVAS_SINGLE_INSTANCE + +void spice_canvas_set_usr_data(SpiceCanvas *spice_canvas, + void *data, + spice_destroy_fn_t destroy_fn) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + if (canvas->usr_data && canvas->usr_data_destroy) { + canvas->usr_data_destroy (canvas->usr_data); + } + canvas->usr_data = data; + canvas->usr_data_destroy = destroy_fn; +} + +void *spice_canvas_get_usr_data(SpiceCanvas *spice_canvas) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + return canvas->usr_data; +} +#endif + + +static void canvas_clip_pixman(CanvasBase *canvas, + pixman_region32_t *dest_region, + SpiceClip *clip) +{ + pixman_region32_intersect(dest_region, dest_region, &canvas->canvas_region); + + switch (clip->type) { + case SPICE_CLIP_TYPE_NONE: + break; + case SPICE_CLIP_TYPE_RECTS: { + uint32_t n = clip->rects->num_rects; + SpiceRect *now = clip->rects->rects; + + pixman_region32_t clip; + + if (spice_pixman_region32_init_rects(&clip, now, n)) { + pixman_region32_intersect(dest_region, dest_region, &clip); + pixman_region32_fini(&clip); + } + + break; + } + default: + spice_warn_if_reached(); + return; + } +} + +static void canvas_mask_pixman(CanvasBase *canvas, + pixman_region32_t *dest_region, + SpiceQMask *mask, int x, int y) +{ + SpiceCanvas *surface_canvas; + pixman_image_t *image, *subimage; + int needs_invert; + pixman_region32_t mask_region; + uint32_t *mask_data; + int mask_x, mask_y; + int mask_width, mask_height, mask_stride; + pixman_box32_t extents; + + if (!mask->bitmap) { + return; + } + + surface_canvas = canvas_get_surface_mask(canvas, mask->bitmap); + if (surface_canvas) { + needs_invert = mask->flags & SPICE_MASK_FLAGS_INVERS; + image = surface_canvas->ops->get_image(surface_canvas, FALSE); + } else { + needs_invert = FALSE; + image = canvas_get_mask(canvas, + mask, + &needs_invert); + } + + mask_data = pixman_image_get_data(image); + mask_width = pixman_image_get_width(image); + mask_height = pixman_image_get_height(image); + mask_stride = pixman_image_get_stride(image); + + mask_x = mask->pos.x; + mask_y = mask->pos.y; + + /* We need to subset the area of the mask that we turn into a region, + because a cached mask may be much larger than what is used for + the clip operation. */ + extents = *pixman_region32_extents(dest_region); + + /* convert from destination pixels to mask pixels */ + extents.x1 -= x - mask_x; + extents.y1 -= y - mask_y; + extents.x2 -= x - mask_x; + extents.y2 -= y - mask_y; + + /* clip to mask size */ + if (extents.x1 < 0) { + extents.x1 = 0; + } + if (extents.x2 >= mask_width) { + extents.x2 = mask_width; + } + if (extents.x2 < extents.x1) { + extents.x2 = extents.x1; + } + if (extents.y1 < 0) { + extents.y1 = 0; + } + if (extents.y2 >= mask_height) { + extents.y2 = mask_height; + } + if (extents.y2 < extents.y1) { + extents.y2 = extents.y1; + } + + /* round down X to even 32 pixels (i.e. uint32_t) */ + extents.x1 = extents.x1 & ~(0x1f); + + mask_data = (uint32_t *)((uint8_t *)mask_data + mask_stride * extents.y1 + extents.x1 / 32); + mask_x -= extents.x1; + mask_y -= extents.y1; + mask_width = extents.x2 - extents.x1; + mask_height = extents.y2 - extents.y1; + + subimage = pixman_image_create_bits(PIXMAN_a1, mask_width, mask_height, + mask_data, mask_stride); + pixman_region32_init_from_image(&mask_region, + subimage); + pixman_image_unref(subimage); + + if (needs_invert) { + pixman_box32_t rect; + + rect.x1 = rect.y1 = 0; + rect.x2 = mask_width; + rect.y2 = mask_height; + + pixman_region32_inverse(&mask_region, &mask_region, &rect); + } + + pixman_region32_translate(&mask_region, + -mask_x + x, -mask_y + y); + + pixman_region32_intersect(dest_region, dest_region, &mask_region); + pixman_region32_fini(&mask_region); + + pixman_image_unref(image); +} + +static void draw_brush(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceBrush *brush, + SpiceROP rop) +{ + CanvasBase *canvas_base = (CanvasBase *)canvas; + uint32_t color; + SpicePattern *pattern; + pixman_image_t *tile; + int offset_x, offset_y; + pixman_box32_t *rects; + int n_rects; + + rects = pixman_region32_rectangles(region, &n_rects); + + switch (brush->type) { + case SPICE_BRUSH_TYPE_SOLID: + color = brush->u.color; + if (rop == SPICE_ROP_COPY) { + canvas->ops->fill_solid_rects(canvas, rects, n_rects, color); + } else { + canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, color, rop); + } + break; + case SPICE_BRUSH_TYPE_PATTERN: { + SpiceCanvas *surface_canvas; + + pattern = &brush->u.pattern; + offset_x = pattern->pos.x; + offset_y = pattern->pos.y; + + surface_canvas = canvas_get_surface(canvas_base, pattern->pat); + if (surface_canvas) { + if (rop == SPICE_ROP_COPY) { + canvas->ops->fill_tiled_rects_from_surface(canvas, rects, n_rects, surface_canvas, + offset_x, offset_y); + } else { + canvas->ops->fill_tiled_rects_rop_from_surface(canvas, rects, n_rects, + surface_canvas, offset_x, offset_y, + rop); + } + } else { + tile = canvas_get_image(canvas_base, pattern->pat, FALSE); + spice_return_if_fail(tile != NULL); + + if (rop == SPICE_ROP_COPY) { + canvas->ops->fill_tiled_rects(canvas, rects, n_rects, tile, offset_x, offset_y); + } else { + canvas->ops->fill_tiled_rects_rop(canvas, rects, n_rects, + tile, offset_x, offset_y, rop); + } + pixman_image_unref(tile); + } + break; + } + case SPICE_BRUSH_TYPE_NONE: + /* Still need to do *something* here, because rop could be e.g invert dest */ + canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, 0, rop); + break; + default: + spice_warn_if_reached(); + return; + } +} + +/* If we're exiting early we may still have to load an image in case + it has to be cached or something */ +static void touch_brush(CanvasBase *canvas, SpiceBrush *brush) +{ + SpicePattern *pattern; + + if (brush->type == SPICE_BRUSH_TYPE_PATTERN) { + pattern = &brush->u.pattern; + canvas_touch_image(canvas, pattern->pat); + } +} + +static void canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + SpiceROP rop; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &fill->mask, + bbox->left, bbox->top); + + rop = ropd_descriptor_to_rop(fill->rop_descriptor, + ROP_INPUT_BRUSH, + ROP_INPUT_DEST); + + if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { + touch_brush(canvas, &fill->brush); + pixman_region32_fini(&dest_region); + return; + } + + draw_brush(spice_canvas, &dest_region, &fill->brush, rop); + + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + SpiceCanvas *surface_canvas; + pixman_image_t *src_image; + SpiceROP rop; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, ©->mask, + bbox->left, bbox->top); + + rop = ropd_descriptor_to_rop(copy->rop_descriptor, + ROP_INPUT_SRC, + ROP_INPUT_DEST); + + if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { + canvas_touch_image(canvas, copy->src_bitmap); + pixman_region32_fini(&dest_region); + return; + } + + surface_canvas = canvas_get_surface(canvas, copy->src_bitmap); + if (surface_canvas) { + if (rect_is_same_size(bbox, ©->src_area)) { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - copy->src_area.left, + bbox->top - copy->src_area.top); + } else { + spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - copy->src_area.left, + bbox->top - copy->src_area.top, + rop); + } + } else { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + copy->src_area.left, + copy->src_area.top, + copy->src_area.right - copy->src_area.left, + copy->src_area.bottom - copy->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + copy->scale_mode); + } else { + spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region, + surface_canvas, + copy->src_area.left, + copy->src_area.top, + copy->src_area.right - copy->src_area.left, + copy->src_area.bottom - copy->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + copy->scale_mode, + rop); + } + } + } else { + src_image = canvas_get_image(canvas, copy->src_bitmap, FALSE); + spice_return_if_fail(src_image != NULL); + + if (rect_is_same_size(bbox, ©->src_area)) { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->blit_image(spice_canvas, &dest_region, + src_image, + bbox->left - copy->src_area.left, + bbox->top - copy->src_area.top); + } else { + spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region, + src_image, + bbox->left - copy->src_area.left, + bbox->top - copy->src_area.top, + rop); + } + } else { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->scale_image(spice_canvas, &dest_region, + src_image, + copy->src_area.left, + copy->src_area.top, + copy->src_area.right - copy->src_area.left, + copy->src_area.bottom - copy->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + copy->scale_mode); + } else { + spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region, + src_image, + copy->src_area.left, + copy->src_area.top, + copy->src_area.right - copy->src_area.left, + copy->src_area.bottom - copy->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + copy->scale_mode, + rop); + } + } + pixman_image_unref(src_image); + } + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + SpiceCanvas *surface_canvas; + pixman_image_t *src_image; + pixman_region32_t dest_region; + uint32_t transparent_color; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + + if (pixman_region32_n_rects (&dest_region) == 0) { + canvas_touch_image(canvas, transparent->src_bitmap); + pixman_region32_fini(&dest_region); + return; + } + + switch (canvas->format) { + case SPICE_SURFACE_FMT_32_xRGB: + case SPICE_SURFACE_FMT_32_ARGB: + transparent_color = transparent->true_color; + break; + case SPICE_SURFACE_FMT_16_555: + transparent_color = rgb_32_to_16_555(transparent->true_color); + break; + case SPICE_SURFACE_FMT_16_565: + transparent_color = rgb_32_to_16_565(transparent->true_color); + break; + default: + transparent_color = 0; + } + + surface_canvas = canvas_get_surface(canvas, transparent->src_bitmap); + if (surface_canvas) { + if (rect_is_same_size(bbox, &transparent->src_area)) { + spice_canvas->ops->colorkey_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - transparent->src_area.left, + bbox->top - transparent->src_area.top, + transparent_color); + } else { + spice_canvas->ops->colorkey_scale_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + transparent->src_area.left, + transparent->src_area.top, + transparent->src_area.right - transparent->src_area.left, + transparent->src_area.bottom - transparent->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + transparent_color); + } + } else { + src_image = canvas_get_image(canvas, transparent->src_bitmap, FALSE); + spice_return_if_fail(src_image != NULL); + + if (rect_is_same_size(bbox, &transparent->src_area)) { + spice_canvas->ops->colorkey_image(spice_canvas, &dest_region, + src_image, + bbox->left - transparent->src_area.left, + bbox->top - transparent->src_area.top, + transparent_color); + } else { + spice_canvas->ops->colorkey_scale_image(spice_canvas, &dest_region, + src_image, + transparent->src_area.left, + transparent->src_area.top, + transparent->src_area.right - transparent->src_area.left, + transparent->src_area.bottom - transparent->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + transparent_color); + } + pixman_image_unref(src_image); + } + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + SpiceCanvas *surface_canvas; + pixman_image_t *src_image; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + + if (alpha_blend->alpha == 0 || + !pixman_region32_not_empty(&dest_region)) { + canvas_touch_image(canvas, alpha_blend->src_bitmap); + pixman_region32_fini(&dest_region); + return; + } + + surface_canvas = canvas_get_surface(canvas, alpha_blend->src_bitmap); + if (surface_canvas) { + if (rect_is_same_size(bbox, &alpha_blend->src_area)) { + spice_canvas->ops->blend_image_from_surface(spice_canvas, &dest_region, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, + surface_canvas, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA, + alpha_blend->src_area.left, + alpha_blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + alpha_blend->alpha); + } else { + spice_canvas->ops->blend_scale_image_from_surface(spice_canvas, &dest_region, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, + surface_canvas, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA, + alpha_blend->src_area.left, + alpha_blend->src_area.top, + alpha_blend->src_area.right - alpha_blend->src_area.left, + alpha_blend->src_area.bottom - alpha_blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + SPICE_IMAGE_SCALE_MODE_NEAREST, + alpha_blend->alpha); + } + } else { + src_image = canvas_get_image(canvas, alpha_blend->src_bitmap, TRUE); + spice_return_if_fail(src_image != NULL); + + if (rect_is_same_size(bbox, &alpha_blend->src_area)) { + spice_canvas->ops->blend_image(spice_canvas, &dest_region, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, + src_image, + alpha_blend->src_area.left, + alpha_blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + alpha_blend->alpha); + } else { + spice_canvas->ops->blend_scale_image(spice_canvas, &dest_region, + alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, + src_image, + alpha_blend->src_area.left, + alpha_blend->src_area.top, + alpha_blend->src_area.right - alpha_blend->src_area.left, + alpha_blend->src_area.bottom - alpha_blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + SPICE_IMAGE_SCALE_MODE_NEAREST, + alpha_blend->alpha); + } + + pixman_image_unref(src_image); + } + + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_image_t *src_image; + pixman_region32_t dest_region; + SpiceCanvas *surface_canvas; + SpiceROP rop; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &opaque->mask, + bbox->left, bbox->top); + + rop = ropd_descriptor_to_rop(opaque->rop_descriptor, + ROP_INPUT_BRUSH, + ROP_INPUT_SRC); + + if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { + canvas_touch_image(canvas, opaque->src_bitmap); + touch_brush(canvas, &opaque->brush); + pixman_region32_fini(&dest_region); + return; + } + + surface_canvas = canvas_get_surface(canvas, opaque->src_bitmap); + if (surface_canvas) { + if (rect_is_same_size(bbox, &opaque->src_area)) { + spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - opaque->src_area.left, + bbox->top - opaque->src_area.top); + } else { + spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + opaque->src_area.left, + opaque->src_area.top, + opaque->src_area.right - opaque->src_area.left, + opaque->src_area.bottom - opaque->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + opaque->scale_mode); + } + } else { + src_image = canvas_get_image(canvas, opaque->src_bitmap, FALSE); + spice_return_if_fail(src_image != NULL); + + if (rect_is_same_size(bbox, &opaque->src_area)) { + spice_canvas->ops->blit_image(spice_canvas, &dest_region, + src_image, + bbox->left - opaque->src_area.left, + bbox->top - opaque->src_area.top); + } else { + spice_canvas->ops->scale_image(spice_canvas, &dest_region, + src_image, + opaque->src_area.left, + opaque->src_area.top, + opaque->src_area.right - opaque->src_area.left, + opaque->src_area.bottom - opaque->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + opaque->scale_mode); + } + pixman_image_unref(src_image); + } + + draw_brush(spice_canvas, &dest_region, &opaque->brush, rop); + + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + SpiceCanvas *surface_canvas; + pixman_image_t *src_image; + pixman_region32_t dest_region; + SpiceROP rop; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &blend->mask, + bbox->left, bbox->top); + + rop = ropd_descriptor_to_rop(blend->rop_descriptor, + ROP_INPUT_SRC, + ROP_INPUT_DEST); + + if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { + canvas_touch_image(canvas, blend->src_bitmap); + pixman_region32_fini(&dest_region); + return; + } + + surface_canvas = canvas_get_surface(canvas, blend->src_bitmap); + if (surface_canvas) { + if (rect_is_same_size(bbox, &blend->src_area)) { + if (rop == SPICE_ROP_COPY) + spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - blend->src_area.left, + bbox->top - blend->src_area.top); + else + spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region, + surface_canvas, + bbox->left - blend->src_area.left, + bbox->top - blend->src_area.top, + rop); + } else { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, + surface_canvas, + blend->src_area.left, + blend->src_area.top, + blend->src_area.right - blend->src_area.left, + blend->src_area.bottom - blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + blend->scale_mode); + } else { + spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region, + surface_canvas, + blend->src_area.left, + blend->src_area.top, + blend->src_area.right - blend->src_area.left, + blend->src_area.bottom - blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + blend->scale_mode, rop); + } + } + } else { + src_image = canvas_get_image(canvas, blend->src_bitmap, FALSE); + spice_return_if_fail(src_image != NULL); + + if (rect_is_same_size(bbox, &blend->src_area)) { + if (rop == SPICE_ROP_COPY) + spice_canvas->ops->blit_image(spice_canvas, &dest_region, + src_image, + bbox->left - blend->src_area.left, + bbox->top - blend->src_area.top); + else + spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region, + src_image, + bbox->left - blend->src_area.left, + bbox->top - blend->src_area.top, + rop); + } else { + if (rop == SPICE_ROP_COPY) { + spice_canvas->ops->scale_image(spice_canvas, &dest_region, + src_image, + blend->src_area.left, + blend->src_area.top, + blend->src_area.right - blend->src_area.left, + blend->src_area.bottom - blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + blend->scale_mode); + } else { + spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region, + src_image, + blend->src_area.left, + blend->src_area.top, + blend->src_area.right - blend->src_area.left, + blend->src_area.bottom - blend->src_area.top, + bbox->left, + bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top, + blend->scale_mode, rop); + } + } + pixman_image_unref(src_image); + } + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + pixman_box32_t *rects; + int n_rects; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &blackness->mask, + bbox->left, bbox->top); + + if (!pixman_region32_not_empty(&dest_region)) { + pixman_region32_fini (&dest_region); + return; + } + + rects = pixman_region32_rectangles(&dest_region, &n_rects); + + spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0x000000); + + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + pixman_box32_t *rects; + int n_rects; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &whiteness->mask, + bbox->left, bbox->top); + + if (!pixman_region32_not_empty(&dest_region)) { + pixman_region32_fini(&dest_region); + return; + } + + rects = pixman_region32_rectangles(&dest_region, &n_rects); + spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0xffffffff); + + pixman_region32_fini(&dest_region); +} + +static void canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + pixman_box32_t *rects; + int n_rects; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &invers->mask, + bbox->left, bbox->top); + + if (!pixman_region32_not_empty(&dest_region)) { + pixman_region32_fini(&dest_region); + return; + } + + rects = pixman_region32_rectangles(&dest_region, &n_rects); + spice_canvas->ops->fill_solid_rects_rop(spice_canvas, rects, n_rects, 0x00000000, + SPICE_ROP_INVERT); + + pixman_region32_fini(&dest_region); +} + +typedef struct { + lineGC base; + SpiceCanvas *canvas; + pixman_region32_t dest_region; + SpiceROP fore_rop; + SpiceROP back_rop; + int solid; + uint32_t color; + int use_surface_canvas; + union { + SpiceCanvas *surface_canvas; + pixman_image_t *tile; + }; + int tile_offset_x; + int tile_offset_y; +} StrokeGC; + +static void stroke_fill_spans(lineGC * pGC, + int num_spans, + SpicePoint *points, + int *widths, + int sorted, + int foreground) +{ + SpiceCanvas *canvas; + StrokeGC *strokeGC; + int i; + SpiceROP rop; + + strokeGC = (StrokeGC *)pGC; + canvas = strokeGC->canvas; + + num_spans = spice_canvas_clip_spans(&strokeGC->dest_region, + points, widths, num_spans, + points, widths, sorted); + + if (foreground) { + rop = strokeGC->fore_rop; + } else { + rop = strokeGC->back_rop; + } + + if (strokeGC->solid) { + if (rop == SPICE_ROP_COPY) { + canvas->ops->fill_solid_spans(canvas, points, widths, num_spans, + strokeGC->color); + } else { + for (i = 0; i < num_spans; i++) { + pixman_box32_t r; + r.x1 = points[i].x; + r.y1 = points[i].y; + r.x2 = points[i].x + widths[i]; + r.y2 = r.y1 + 1; + canvas->ops->fill_solid_rects_rop(canvas, &r, 1, + strokeGC->color, rop); + } + } + } else { + if (rop == SPICE_ROP_COPY) { + for (i = 0; i < num_spans; i++) { + pixman_box32_t r; + r.x1 = points[i].x; + r.y1 = points[i].y; + r.x2 = points[i].x + widths[i]; + r.y2 = r.y1 + 1; + canvas->ops->fill_tiled_rects(canvas, &r, 1, + strokeGC->tile, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y); + } + } else { + for (i = 0; i < num_spans; i++) { + pixman_box32_t r; + r.x1 = points[i].x; + r.y1 = points[i].y; + r.x2 = points[i].x + widths[i]; + r.y2 = r.y1 + 1; + canvas->ops->fill_tiled_rects_rop(canvas, &r, 1, + strokeGC->tile, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y, rop); + } + } + } +} + +static void stroke_fill_rects(lineGC * pGC, + int num_rects, + pixman_rectangle32_t *rects, + int foreground) +{ + SpiceCanvas *canvas; + pixman_region32_t area; + pixman_box32_t *boxes; + StrokeGC *strokeGC; + SpiceROP rop; + int i; + pixman_box32_t *area_rects; + int n_area_rects; + + strokeGC = (StrokeGC *)pGC; + canvas = strokeGC->canvas; + + if (foreground) { + rop = strokeGC->fore_rop; + } else { + rop = strokeGC->back_rop; + } + + /* TODO: We can optimize this for more common cases where + dest is one rect */ + + boxes = spice_new(pixman_box32_t, num_rects); + for (i = 0; i < num_rects; i++) { + boxes[i].x1 = rects[i].x; + boxes[i].y1 = rects[i].y; + boxes[i].x2 = rects[i].x + rects[i].width; + boxes[i].y2 = rects[i].y + rects[i].height; + } + pixman_region32_init_rects(&area, boxes, num_rects); + pixman_region32_intersect(&area, &area, &strokeGC->dest_region); + free(boxes); + + area_rects = pixman_region32_rectangles(&area, &n_area_rects); + + if (strokeGC->solid) { + if (rop == SPICE_ROP_COPY) { + canvas->ops->fill_solid_rects(canvas, area_rects, n_area_rects, + strokeGC->color); + } else { + canvas->ops->fill_solid_rects_rop(canvas, area_rects, n_area_rects, + strokeGC->color, rop); + } + } else { + if (rop == SPICE_ROP_COPY) { + if (strokeGC->use_surface_canvas) { + canvas->ops->fill_tiled_rects_from_surface(canvas, area_rects, n_area_rects, + strokeGC->surface_canvas, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y); + } else { + canvas->ops->fill_tiled_rects(canvas, area_rects, n_area_rects, + strokeGC->tile, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y); + } + } else { + if (strokeGC->use_surface_canvas) { + canvas->ops->fill_tiled_rects_rop_from_surface(canvas, area_rects, n_area_rects, + strokeGC->surface_canvas, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y, + rop); + } else { + canvas->ops->fill_tiled_rects_rop(canvas, area_rects, n_area_rects, + strokeGC->tile, + strokeGC->tile_offset_x, + strokeGC->tile_offset_y, + rop); + } + } + } + + pixman_region32_fini(&area); +} + +typedef struct { + SpicePoint *points; + int num_points; + int size; +} StrokeLines; + +static void stroke_lines_init(StrokeLines *lines) +{ + lines->points = spice_new(SpicePoint, 10); + lines->size = 10; + lines->num_points = 0; +} + +static void stroke_lines_free(StrokeLines *lines) +{ + free(lines->points); +} + +static void stroke_lines_append(StrokeLines *lines, + int x, int y) +{ + if (lines->num_points == lines->size) { + lines->size *= 2; + lines->points = spice_renew(SpicePoint, lines->points, lines->size); + } + lines->points[lines->num_points].x = x; + lines->points[lines->num_points].y = y; + lines->num_points++; +} + +static void stroke_lines_append_fix(StrokeLines *lines, + SpicePointFix *point) +{ + stroke_lines_append(lines, + fix_to_int(point->x), + fix_to_int(point->y)); +} + +static inline int64_t dot(SPICE_FIXED28_4 x1, + SPICE_FIXED28_4 y1, + SPICE_FIXED28_4 x2, + SPICE_FIXED28_4 y2) +{ + return (((int64_t)x1) *((int64_t)x2) + + ((int64_t)y1) *((int64_t)y2)) >> 4; +} + +static inline int64_t dot2(SPICE_FIXED28_4 x, + SPICE_FIXED28_4 y) +{ + return (((int64_t)x) *((int64_t)x) + + ((int64_t)y) *((int64_t)y)) >> 4; +} + +static void subdivide_bezier(StrokeLines *lines, + SpicePointFix point0, + SpicePointFix point1, + SpicePointFix point2, + SpicePointFix point3) +{ + int64_t A2, B2, C2, AB, CB, h1, h2; + + A2 = dot2(point1.x - point0.x, + point1.y - point0.y); + B2 = dot2(point3.x - point0.x, + point3.y - point0.y); + C2 = dot2(point2.x - point3.x, + point2.y - point3.y); + + AB = dot(point1.x - point0.x, + point1.y - point0.y, + point3.x - point0.x, + point3.y - point0.y); + + CB = dot(point2.x - point3.x, + point2.y - point3.y, + point0.x - point3.x, + point0.y - point3.y); + + h1 = (A2*B2 - AB*AB) >> 3; + h2 = (C2*B2 - CB*CB) >> 3; + + if (h1 < B2 && h2 < B2) { + /* deviation squared less than half a pixel, use straight line */ + stroke_lines_append_fix(lines, &point3); + } else { + SpicePointFix point01, point23, point12, point012, point123, point0123; + + point01.x = (point0.x + point1.x) / 2; + point01.y = (point0.y + point1.y) / 2; + point12.x = (point1.x + point2.x) / 2; + point12.y = (point1.y + point2.y) / 2; + point23.x = (point2.x + point3.x) / 2; + point23.y = (point2.y + point3.y) / 2; + point012.x = (point01.x + point12.x) / 2; + point012.y = (point01.y + point12.y) / 2; + point123.x = (point12.x + point23.x) / 2; + point123.y = (point12.y + point23.y) / 2; + point0123.x = (point012.x + point123.x) / 2; + point0123.y = (point012.y + point123.y) / 2; + + subdivide_bezier(lines, point0, point01, point012, point0123); + subdivide_bezier(lines, point0123, point123, point23, point3); + } +} + +static void stroke_lines_append_bezier(StrokeLines *lines, + SpicePointFix *point1, + SpicePointFix *point2, + SpicePointFix *point3) +{ + SpicePointFix point0; + + point0.x = int_to_fix(lines->points[lines->num_points-1].x); + point0.y = int_to_fix(lines->points[lines->num_points-1].y); + + subdivide_bezier(lines, point0, *point1, *point2, *point3); +} + +static void stroke_lines_draw(StrokeLines *lines, + lineGC *gc, + int dashed) +{ + if (lines->num_points != 0) { + if (dashed) { + spice_canvas_zero_dash_line(gc, CoordModeOrigin, + lines->num_points, lines->points); + } else { + spice_canvas_zero_line(gc, CoordModeOrigin, + lines->num_points, lines->points); + } + lines->num_points = 0; + } +} + + +static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, + SpiceClip *clip, SpiceStroke *stroke) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + SpiceCanvas *surface_canvas = NULL; + StrokeGC gc; + lineGCOps ops = { + stroke_fill_spans, + stroke_fill_rects + }; + StrokeLines lines; + unsigned int i; + int dashed; + + memset(&gc, 0, sizeof(gc)); + + pixman_region32_init_rect(&gc.dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &gc.dest_region, clip); + + if (!pixman_region32_not_empty(&gc.dest_region)) { + touch_brush(canvas, &stroke->brush); + pixman_region32_fini(&gc.dest_region); + return; + } + + gc.canvas = spice_canvas; + gc.fore_rop = ropd_descriptor_to_rop(stroke->fore_mode, + ROP_INPUT_BRUSH, + ROP_INPUT_DEST); + gc.back_rop = ropd_descriptor_to_rop(stroke->back_mode, + ROP_INPUT_BRUSH, + ROP_INPUT_DEST); + + gc.base.width = canvas->width; + gc.base.height = canvas->height; + gc.base.alu = gc.fore_rop; + gc.base.lineWidth = 0; + + /* dash */ + gc.base.dashOffset = 0; + gc.base.dash = NULL; + gc.base.numInDashList = 0; + gc.base.lineStyle = LineSolid; + /* win32 cosmetic lines are endpoint-exclusive, so use CapNotLast */ + gc.base.capStyle = CapNotLast; + gc.base.joinStyle = JoinMiter; + gc.base.ops = &ops; + + dashed = 0; + if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { + SPICE_FIXED28_4 *style = stroke->attr.style; + int nseg; + + dashed = 1; + + nseg = stroke->attr.style_nseg; + + /* To truly handle back_mode we should use LineDoubleDash here + and treat !foreground as back_rop using the same brush. + However, using the same brush for that seems wrong. + The old cairo backend was stroking the non-dashed line with + rop_mode before enabling dashes for the foreground which is + not right either. The gl an gdi backend don't use back_mode + at all */ + gc.base.lineStyle = LineOnOffDash; + gc.base.dash = (unsigned char *)spice_malloc(nseg); + gc.base.numInDashList = nseg; + + if (stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP) { + gc.base.dash[stroke->attr.style_nseg - 1] = fix_to_int(style[0]); + for (i = 0; i < (unsigned int)(stroke->attr.style_nseg - 1); i++) { + gc.base.dash[i] = fix_to_int(style[i+1]); + } + gc.base.dashOffset = gc.base.dash[0]; + } else { + for (i = 0; i < stroke->attr.style_nseg; i++) { + gc.base.dash[i] = fix_to_int(style[i]); + } + } + } + + switch (stroke->brush.type) { + case SPICE_BRUSH_TYPE_NONE: + gc.solid = TRUE; + gc.color = 0; + break; + case SPICE_BRUSH_TYPE_SOLID: + gc.solid = TRUE; + gc.color = stroke->brush.u.color; + break; + case SPICE_BRUSH_TYPE_PATTERN: + gc.solid = FALSE; + surface_canvas = canvas_get_surface(canvas, + stroke->brush.u.pattern.pat); + if (surface_canvas) { + gc.use_surface_canvas = TRUE; + gc.surface_canvas = surface_canvas; + } else { + gc.use_surface_canvas = FALSE; + gc.tile = canvas_get_image(canvas, + stroke->brush.u.pattern.pat, + FALSE); + } + gc.tile_offset_x = stroke->brush.u.pattern.pos.x; + gc.tile_offset_y = stroke->brush.u.pattern.pos.y; + break; + default: + spice_warn_if_reached(); + return; + } + + stroke_lines_init(&lines); + + for (i = 0; i < stroke->path->num_segments; i++) { + SpicePathSeg *seg = stroke->path->segments[i]; + SpicePointFix* point, *end_point; + + point = seg->points; + end_point = point + seg->count; + + if (seg->flags & SPICE_PATH_BEGIN) { + stroke_lines_draw(&lines, (lineGC *)&gc, dashed); + stroke_lines_append_fix(&lines, point); + point++; + } + + if (seg->flags & SPICE_PATH_BEZIER) { + spice_return_if_fail((point - end_point) % 3 == 0); + for (; point + 2 < end_point; point += 3) { + stroke_lines_append_bezier(&lines, + &point[0], + &point[1], + &point[2]); + } + } else + { + for (; point < end_point; point++) { + stroke_lines_append_fix(&lines, point); + } + } + if (seg->flags & SPICE_PATH_END) { + if (seg->flags & SPICE_PATH_CLOSE) { + stroke_lines_append(&lines, + lines.points[0].x, lines.points[0].y); + } + stroke_lines_draw(&lines, (lineGC *)&gc, dashed); + } + } + + stroke_lines_draw(&lines, (lineGC *)&gc, dashed); + + free(gc.base.dash); + stroke_lines_free(&lines); + + if (!gc.solid && gc.tile && !surface_canvas) { + pixman_image_unref(gc.tile); + } + + pixman_region32_fini(&gc.dest_region); +} + + +//need surfaces handling here !!! +static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, + SpiceClip *clip, SpiceRop3 *rop3) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + SpiceCanvas *surface_canvas; + pixman_region32_t dest_region; + pixman_image_t *d; + pixman_image_t *s; + SpicePoint src_pos; + int width; + int heigth; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + canvas_mask_pixman(canvas, &dest_region, &rop3->mask, + bbox->left, bbox->top); + + width = bbox->right - bbox->left; + heigth = bbox->bottom - bbox->top; + + d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth, FALSE); + surface_canvas = canvas_get_surface(canvas, rop3->src_bitmap); + if (surface_canvas) { + s = surface_canvas->ops->get_image(surface_canvas, FALSE); + } else { + s = canvas_get_image(canvas, rop3->src_bitmap, FALSE); + } + + if (!rect_is_same_size(bbox, &rop3->src_area)) { + pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, width, heigth, + rop3->scale_mode); + pixman_image_unref(s); + s = scaled_s; + src_pos.x = 0; + src_pos.y = 0; + } else { + src_pos.x = rop3->src_area.left; + src_pos.y = rop3->src_area.top; + } + if (pixman_image_get_width(s) - src_pos.x < width || + pixman_image_get_height(s) - src_pos.y < heigth) { + spice_critical("bad src bitmap size"); + return; + } + if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + SpiceCanvas *_surface_canvas; + pixman_image_t *p; + + _surface_canvas = canvas_get_surface(canvas, rop3->brush.u.pattern.pat); + if (_surface_canvas) { + p = _surface_canvas->ops->get_image(_surface_canvas, FALSE); + } else { + p = canvas_get_image(canvas, rop3->brush.u.pattern.pat, FALSE); + } + SpicePoint pat_pos; + + pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p); + pat_pos.y = (bbox->top - rop3->brush.u.pattern.pos.y) % pixman_image_get_height(p); + do_rop3_with_pattern(rop3->rop3, d, s, &src_pos, p, &pat_pos); + pixman_image_unref(p); + } else { + do_rop3_with_color(rop3->rop3, d, s, &src_pos, rop3->brush.u.color); + } + pixman_image_unref(s); + + spice_canvas->ops->blit_image(spice_canvas, &dest_region, d, + bbox->left, + bbox->top); + + pixman_image_unref(d); + + pixman_region32_fini(&dest_region); +} + +static void transform_to_pixman_transform(SpiceTransform *transform, + pixman_transform_t *p) +{ + p->matrix[0][0] = transform->t00; + p->matrix[0][1] = transform->t01; + p->matrix[0][2] = transform->t02; + p->matrix[1][0] = transform->t10; + p->matrix[1][1] = transform->t11; + p->matrix[1][2] = transform->t12; + p->matrix[2][0] = 0; + p->matrix[2][1] = 0; + p->matrix[2][2] = pixman_fixed_1; +} + +#define MASK(lo, hi) \ + (((1U << (hi)) - 1) - (((1U << (lo))) - 1)) + +#define EXTRACT(v, lo, hi) \ + ((v & MASK(lo, hi)) >> lo) + +static void canvas_draw_composite(SpiceCanvas *spice_canvas, SpiceRect *bbox, + SpiceClip *clip, SpiceComposite *composite) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + SpiceCanvas *surface_canvas; + pixman_region32_t dest_region; + pixman_image_t *d; + pixman_image_t *s; + pixman_image_t *m; + pixman_repeat_t src_repeat; + pixman_filter_t src_filter; + pixman_op_t op; + pixman_transform_t transform; + int width, height; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + + width = bbox->right - bbox->left; + height = bbox->bottom - bbox->top; + + /* Dest */ + d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, height, + (composite->flags & SPICE_COMPOSITE_DEST_OPAQUE)); + + /* Src */ + surface_canvas = canvas_get_surface(canvas, composite->src_bitmap); + if (surface_canvas) { + s = surface_canvas->ops->get_image(surface_canvas, + (composite->flags & SPICE_COMPOSITE_SOURCE_OPAQUE)); + } else { + s = canvas_get_image(canvas, composite->src_bitmap, FALSE); + } + if (composite->flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM) + { + transform_to_pixman_transform (&composite->src_transform, &transform); + pixman_image_set_transform (s, &transform); + } + src_filter = (pixman_filter_t) EXTRACT (composite->flags, 8, 11); + src_repeat = (pixman_repeat_t) EXTRACT (composite->flags, 14, 16); + pixman_image_set_filter (s, src_filter, NULL, 0); + pixman_image_set_repeat (s, src_repeat); + + /* Mask */ + m = NULL; + if (composite->flags & SPICE_COMPOSITE_HAS_MASK) { + pixman_filter_t mask_filter = (pixman_filter_t) EXTRACT (composite->flags, 11, 14); + pixman_repeat_t mask_repeat = (pixman_repeat_t) EXTRACT (composite->flags, 16, 18); + pixman_bool_t component_alpha = EXTRACT (composite->flags, 18, 19); + + surface_canvas = canvas_get_surface(canvas, composite->mask_bitmap); + if (surface_canvas) { + m = surface_canvas->ops->get_image(surface_canvas, FALSE); + } else { + m = canvas_get_image(canvas, composite->mask_bitmap, FALSE); + } + + if (composite->flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM) { + transform_to_pixman_transform (&composite->mask_transform, &transform); + pixman_image_set_transform (m, &transform); + } + + pixman_image_set_repeat (m, mask_repeat); + pixman_image_set_filter (m, mask_filter, NULL, 0); + pixman_image_set_component_alpha (m, component_alpha); + } + + op = (pixman_op_t) EXTRACT (composite->flags, 0, 8); + + pixman_image_composite32 (op, s, m, d, + composite->src_origin.x, composite->src_origin.y, + composite->mask_origin.x, composite->mask_origin.y, + 0, 0, width, height); + + pixman_image_unref(s); + if (m) + pixman_image_unref(m); + + spice_canvas->ops->blit_image(spice_canvas, &dest_region, d, + bbox->left, + bbox->top); + + pixman_image_unref(d); + + pixman_region32_fini(&dest_region); +} + +static void canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_t dest_region; + int dx, dy; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(canvas, &dest_region, clip); + + dx = bbox->left - src_pos->x; + dy = bbox->top - src_pos->y; + + if (dx != 0 || dy != 0) { + pixman_region32_t src_region; + + /* Clip so we don't read outside canvas */ + pixman_region32_init_rect(&src_region, + dx, dy, + canvas->width, + canvas->height); + pixman_region32_intersect(&dest_region, &dest_region, &src_region); + pixman_region32_fini(&src_region); + + spice_canvas->ops->copy_region(spice_canvas, &dest_region, dx, dy); + } + + pixman_region32_fini(&dest_region); +} + + + +static void canvas_base_group_start(SpiceCanvas *spice_canvas, QRegion *region) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_fini(&canvas->canvas_region); + + /* Make sure we always clip to canvas size */ + pixman_region32_init_rect(&canvas->canvas_region, + 0, 0, + canvas->width, + canvas->height); + + pixman_region32_intersect(&canvas->canvas_region, &canvas->canvas_region, region); +} + +static void canvas_base_group_end(SpiceCanvas *spice_canvas) +{ + CanvasBase *canvas = (CanvasBase *)spice_canvas; + pixman_region32_fini(&canvas->canvas_region); + pixman_region32_init_rect(&canvas->canvas_region, + 0, 0, + canvas->width, + canvas->height); +} + + +static void unimplemented_op(SpiceCanvas *canvas) +{ + spice_critical("unimplemented canvas operation"); +} + +inline static void canvas_base_init_ops(SpiceCanvasOps *ops) +{ + void **ops_cast; + unsigned i; + + ops_cast = (void **)ops; + for (i = 0; i < sizeof(SpiceCanvasOps) / sizeof(void *); i++) { + ops_cast[i] = (void *) unimplemented_op; + } + + ops->draw_fill = canvas_draw_fill; + ops->draw_copy = canvas_draw_copy; + ops->draw_opaque = canvas_draw_opaque; + ops->copy_bits = canvas_copy_bits; + ops->draw_blend = canvas_draw_blend; + ops->draw_blackness = canvas_draw_blackness; + ops->draw_whiteness = canvas_draw_whiteness; + ops->draw_invers = canvas_draw_invers; + ops->draw_transparent = canvas_draw_transparent; + ops->draw_alpha_blend = canvas_draw_alpha_blend; + ops->draw_stroke = canvas_draw_stroke; + ops->draw_rop3 = canvas_draw_rop3; + ops->draw_composite = canvas_draw_composite; + ops->group_start = canvas_base_group_start; + ops->group_end = canvas_base_group_end; +} + +static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, + int width, int height, uint32_t format + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ) +{ + canvas->parent.ops = ops; + canvas->quic_data.usr.error = quic_usr_error; + canvas->quic_data.usr.warn = quic_usr_warn; + canvas->quic_data.usr.info = quic_usr_warn; + canvas->quic_data.usr.malloc = quic_usr_malloc; + canvas->quic_data.usr.free = quic_usr_free; + canvas->quic_data.usr.more_space = quic_usr_more_space; + canvas->quic_data.usr.more_lines = quic_usr_more_lines; + if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) { + return 0; + } + + canvas->lz_data.usr.error = lz_usr_error; + canvas->lz_data.usr.warn = lz_usr_warn; + canvas->lz_data.usr.info = lz_usr_warn; + canvas->lz_data.usr.malloc = lz_usr_malloc; + canvas->lz_data.usr.free = lz_usr_free; + canvas->lz_data.usr.more_space = lz_usr_more_space; + canvas->lz_data.usr.more_lines = lz_usr_more_lines; + if (!(canvas->lz_data.lz = lz_create(&canvas->lz_data.usr))) { + return 0; + } + + canvas->surfaces = surfaces; + canvas->glz_data.decoder = glz_decoder; + canvas->jpeg = jpeg_decoder; + canvas->zlib = zlib_decoder; + + canvas->format = format; + + /* TODO: This is all wrong now */ + if (SPICE_SURFACE_FMT_DEPTH(format) == 16) { + canvas->color_shift = 5; + canvas->color_mask = 0x1f; + } else { + canvas->color_shift = 8; + canvas->color_mask = 0xff; + } + + canvas->width = width; + canvas->height = height; + pixman_region32_init_rect(&canvas->canvas_region, + 0, 0, + canvas->width, + canvas->height); + + canvas->bits_cache = bits_cache; +#ifdef SW_CANVAS_CACHE + canvas->palette_cache = palette_cache; +#endif + +#ifdef WIN32 + canvas->dc = NULL; +#endif + +#ifdef GDI_CANVAS + canvas->dc = create_compatible_dc(); + if (!canvas->dc) { + lz_destroy(canvas->lz_data.lz); + return 0; + } +#endif + return 1; +} diff --git a/spice-common/common/canvas_base.h b/spice-common/common/canvas_base.h new file mode 100644 index 0000000..637cdc1 --- /dev/null +++ b/spice-common/common/canvas_base.h @@ -0,0 +1,322 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_CANVAS_BASE +#define _H_CANVAS_BASE + +#include + +#include "pixman_utils.h" +#include "lz.h" +#include "region.h" +#include "draw.h" +#ifdef WIN32 +#include +#endif + +SPICE_BEGIN_DECLS + +typedef void (*spice_destroy_fn_t)(void *data); + +typedef struct _SpiceImageCache SpiceImageCache; +typedef struct _SpiceImageSurfaces SpiceImageSurfaces; +typedef struct _SpicePaletteCache SpicePaletteCache; +typedef struct _SpiceGlzDecoder SpiceGlzDecoder; +typedef struct _SpiceJpegDecoder SpiceJpegDecoder; +typedef struct _SpiceZlibDecoder SpiceZlibDecoder; +typedef struct _SpiceCanvas SpiceCanvas; + +typedef struct { + void (*put)(SpiceImageCache *cache, + uint64_t id, + pixman_image_t *surface); + pixman_image_t *(*get)(SpiceImageCache *cache, + uint64_t id); +#ifdef SW_CANVAS_CACHE + void (*put_lossy)(SpiceImageCache *cache, + uint64_t id, + pixman_image_t *surface); + void (*replace_lossy)(SpiceImageCache *cache, + uint64_t id, + pixman_image_t *surface); + pixman_image_t *(*get_lossless)(SpiceImageCache *cache, + uint64_t id); +#endif +} SpiceImageCacheOps; + +struct _SpiceImageCache { + SpiceImageCacheOps *ops; +}; + +typedef struct { + SpiceCanvas *(*get)(SpiceImageSurfaces *surfaces, + uint32_t surface_id); +} SpiceImageSurfacesOps; + +struct _SpiceImageSurfaces { + SpiceImageSurfacesOps *ops; +}; + +typedef struct { + void (*put)(SpicePaletteCache *cache, + SpicePalette *palette); + SpicePalette *(*get)(SpicePaletteCache *cache, + uint64_t id); + void (*release)(SpicePaletteCache *cache, + SpicePalette *palette); +} SpicePaletteCacheOps; + +struct _SpicePaletteCache { + SpicePaletteCacheOps *ops; +}; + +typedef struct { + void (*decode)(SpiceGlzDecoder *decoder, + uint8_t *data, + SpicePalette *plt, + void *usr_data); +} SpiceGlzDecoderOps; + +struct _SpiceGlzDecoder { + SpiceGlzDecoderOps *ops; +}; + + +typedef struct SpiceJpegDecoderOps { + void (*begin_decode)(SpiceJpegDecoder *decoder, + uint8_t* data, + int data_size, + int* out_width, + int* out_height); + void (*decode)(SpiceJpegDecoder *decoder, + uint8_t* dest, + int stride, + int format); +} SpiceJpegDecoderOps; + +struct _SpiceJpegDecoder { + SpiceJpegDecoderOps *ops; +}; + +typedef struct { + void (*decode)(SpiceZlibDecoder *decoder, + uint8_t *data, + int data_size, + uint8_t *dest, + int dest_size); +} SpiceZlibDecoderOps; + +struct _SpiceZlibDecoder { + SpiceZlibDecoderOps *ops; +}; + +typedef struct { + void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill); + void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy); + void (*draw_opaque)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque); + void (*copy_bits)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos); + void (*draw_text)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text); + void (*draw_stroke)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke); + void (*draw_rop3)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3); + void (*draw_composite)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceComposite *composite); + void (*draw_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend); + void (*draw_blackness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness); + void (*draw_whiteness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness); + void (*draw_invers)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers); + void (*draw_transparent)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent); + void (*draw_alpha_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend); + void (*put_image)(SpiceCanvas *canvas, +#ifdef WIN32 + HDC dc, +#endif + const SpiceRect *dest, const uint8_t *src_data, + uint32_t src_width, uint32_t src_height, int src_stride, + const QRegion *clip); + void (*clear)(SpiceCanvas *canvas); + void (*read_bits)(SpiceCanvas *canvas, uint8_t *dest, int dest_stride, const SpiceRect *area); + void (*group_start)(SpiceCanvas *canvas, QRegion *region); + void (*group_end)(SpiceCanvas *canvas); + void (*destroy)(SpiceCanvas *canvas); + + /* Implementation vfuncs */ + void (*fill_solid_spans)(SpiceCanvas *canvas, + SpicePoint *points, + int *widths, + int n_spans, + uint32_t color); + void (*fill_solid_rects)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + uint32_t color); + void (*fill_solid_rects_rop)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + uint32_t color, + SpiceROP rop); + void (*fill_tiled_rects)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y); + void (*fill_tiled_rects_from_surface)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + SpiceCanvas *tile, + int offset_x, int offset_y); + void (*fill_tiled_rects_rop)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y, + SpiceROP rop); + void (*fill_tiled_rects_rop_from_surface)(SpiceCanvas *canvas, + pixman_box32_t *rects, + int n_rects, + SpiceCanvas *tile, + int offset_x, int offset_y, + SpiceROP rop); + void (*blit_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y); + void (*blit_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int offset_x, int offset_y); + void (*blit_image_rop)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + SpiceROP rop); + void (*blit_image_rop_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int offset_x, int offset_y, + SpiceROP rop); + void (*scale_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode); + void (*scale_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode); + void (*scale_image_rop)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, SpiceROP rop); + void (*scale_image_rop_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, SpiceROP rop); + void (*blend_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src_image, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int overall_alpha); + void (*blend_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + int dest_has_alpha, + SpiceCanvas *src_image, + int src_has_alpha, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int overall_alpha); + void (*blend_scale_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, + int overall_alpha); + void (*blend_scale_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + int dest_has_alpha, + SpiceCanvas *src_image, + int src_has_alpha, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, + int overall_alpha); + void (*colorkey_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + uint32_t transparent_color); + void (*colorkey_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int offset_x, int offset_y, + uint32_t transparent_color); + void (*colorkey_scale_image)(SpiceCanvas *canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + uint32_t transparent_color); + void (*colorkey_scale_image_from_surface)(SpiceCanvas *canvas, + pixman_region32_t *region, + SpiceCanvas *src_image, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + uint32_t transparent_color); + void (*copy_region)(SpiceCanvas *canvas, + pixman_region32_t *dest_region, + int dx, int dy); + pixman_image_t *(*get_image)(SpiceCanvas *canvas, int force_opaque); +} SpiceCanvasOps; + +void spice_canvas_set_usr_data(SpiceCanvas *canvas, void *data, spice_destroy_fn_t destroy_fn); +void *spice_canvas_get_usr_data(SpiceCanvas *canvas); + +struct _SpiceCanvas { + SpiceCanvasOps *ops; +}; + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/canvas_utils.c b/spice-common/common/canvas_utils.c new file mode 100644 index 0000000..0be761a --- /dev/null +++ b/spice-common/common/canvas_utils.c @@ -0,0 +1,318 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "spice_common.h" + +#include "canvas_utils.h" +#include "mem.h" + +#ifdef WIN32 +static int gdi_handlers = 0; +#endif + +static void release_data(SPICE_GNUC_UNUSED pixman_image_t *image, + void *release_data) +{ + PixmanData *data = (PixmanData *)release_data; + +#ifdef WIN32 + if (data->bitmap) { + DeleteObject((HBITMAP)data->bitmap); + CloseHandle(data->mutex); + gdi_handlers--; + } +#endif + free(data->data); + + free(data); +} + +static PixmanData * +pixman_image_add_data(pixman_image_t *image) +{ + PixmanData *data; + + data = (PixmanData *)pixman_image_get_destroy_data(image); + if (data == NULL) { + data = (PixmanData *)calloc(1, sizeof(PixmanData)); + if (data == NULL) { + spice_error("out of memory"); + } + pixman_image_set_destroy_function(image, + release_data, + data); + } + + return data; +} + +void +spice_pixman_image_set_format(pixman_image_t *image, + pixman_format_code_t format) +{ + PixmanData *data; + + data = pixman_image_add_data(image); + data->format = format; +} + + +int spice_pixman_image_get_format(pixman_image_t *image, pixman_format_code_t *format) +{ + PixmanData *data; + + spice_return_val_if_fail(format != NULL, 0); + + data = (PixmanData *)pixman_image_get_destroy_data(image); + if (data != NULL && data->format != 0) { + *format = data->format; + return 1; + } + + spice_warn_if_reached(); + return 0; +} + +static inline pixman_image_t *__surface_create_stride(pixman_format_code_t format, int width, int height, + int stride) +{ + uint8_t *data; + uint8_t *stride_data; + pixman_image_t *surface; + PixmanData *pixman_data; + + data = (uint8_t *)spice_malloc_n(abs(stride), height); + if (stride < 0) { + stride_data = data + (-stride) * (height - 1); + } else { + stride_data = data; + } + + surface = pixman_image_create_bits(format, width, height, (uint32_t *)stride_data, stride); + + if (surface == NULL) { + free(data); + data = NULL; + spice_error("create surface failed, out of memory"); + } + + pixman_data = pixman_image_add_data(surface); + pixman_data->data = data; + pixman_data->format = format; + + return surface; +} + +#ifdef WIN32 +pixman_image_t *surface_create(HDC dc, pixman_format_code_t format, + int width, int height, int top_down) +#else +pixman_image_t * surface_create(pixman_format_code_t format, int width, int height, int top_down) +#endif +{ +#ifdef WIN32 + /* + * Windows xp allow only 10,000 of gdi handlers, considering the fact that + * we limit here the number to 5000, we dont use atomic operations to sync + * this calculation against the other canvases (in case of multiple + * monitors), in worst case there will be little more than 5000 gdi + * handlers. + */ + if (dc && gdi_handlers < 5000) { + uint8_t *data; + uint8_t *src; + struct { + BITMAPINFO inf; + RGBQUAD palette[255]; + } bitmap_info; + int nstride; + pixman_image_t *surface; + PixmanData *pixman_data; + HBITMAP bitmap; + HANDLE mutex; + + memset(&bitmap_info, 0, sizeof(bitmap_info)); + bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); + bitmap_info.inf.bmiHeader.biWidth = width; + + bitmap_info.inf.bmiHeader.biHeight = (!top_down) ? height : -height; + + bitmap_info.inf.bmiHeader.biPlanes = 1; + switch (format) { + case PIXMAN_a8r8g8b8: + case PIXMAN_x8r8g8b8: +#ifdef WORDS_BIGENDIAN + case PIXMAN_b8g8r8a8: + case PIXMAN_b8g8r8x8: +#endif + bitmap_info.inf.bmiHeader.biBitCount = 32; + nstride = width * 4; + break; + case PIXMAN_r8g8b8: +#ifdef WORDS_BIGENDIAN + case PIXMAN_b8g8r8: +#endif + bitmap_info.inf.bmiHeader.biBitCount = 24; + nstride = SPICE_ALIGN(width * 3, 4); + break; + case PIXMAN_x1r5g5b5: + case PIXMAN_r5g6b5: + bitmap_info.inf.bmiHeader.biBitCount = 16; + nstride = SPICE_ALIGN(width * 2, 4); + break; + case PIXMAN_a8: + bitmap_info.inf.bmiHeader.biBitCount = 8; + nstride = SPICE_ALIGN(width, 4); + break; + case PIXMAN_a1: + bitmap_info.inf.bmiHeader.biBitCount = 1; + nstride = SPICE_ALIGN(width, 32) / 8; + break; + default: + spice_error("invalid format"); + return NULL; + } + + bitmap_info.inf.bmiHeader.biCompression = BI_RGB; + + mutex = CreateMutex(NULL, 0, NULL); + if (!mutex) { + spice_error("Unable to CreateMutex"); + } + + bitmap = CreateDIBSection(dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0); + if (!bitmap) { + CloseHandle(mutex); + spice_error("Unable to CreateDIBSection"); + } + + if (top_down) { + src = data; + } else { + src = data + nstride * (height - 1); + nstride = -nstride; + } + + surface = pixman_image_create_bits(format, width, height, (uint32_t *)src, nstride); + if (surface == NULL) { + CloseHandle(mutex); + DeleteObject(bitmap); + spice_error("create surface failed, out of memory"); + } + pixman_data = pixman_image_add_data(surface); + pixman_data->format = format; + pixman_data->bitmap = bitmap; + pixman_data->mutex = mutex; + gdi_handlers++; + return surface; + } else { +#endif + if (top_down) { + pixman_image_t *surface; + PixmanData *data; + + surface = pixman_image_create_bits(format, width, height, NULL, 0); + data = pixman_image_add_data(surface); + data->format = format; + return surface; + } else { + // NOTE: we assume here that the lz decoders always decode to RGB32. + int stride = 0; + switch (format) { + case PIXMAN_a8r8g8b8: + case PIXMAN_x8r8g8b8: +#ifdef WORDS_BIGENDIAN + case PIXMAN_b8g8r8a8: + case PIXMAN_b8g8r8x8: +#endif + stride = width * 4; + break; + case PIXMAN_r8g8b8: +#ifdef WORDS_BIGENDIAN + case PIXMAN_b8g8r8: +#endif + // NOTE: LZ4 also decodes to RGB24 + stride = SPICE_ALIGN(width * 3, 4); + break; + case PIXMAN_x1r5g5b5: + case PIXMAN_r5g6b5: + stride = SPICE_ALIGN(width * 2, 4); + break; + case PIXMAN_a8: + stride = SPICE_ALIGN(width, 4); + break; + case PIXMAN_a1: + stride = SPICE_ALIGN(width, 32) / 8; + break; + default: + spice_error("invalid format"); + } + stride = -stride; + return __surface_create_stride(format, width, height, stride); + } +#ifdef WIN32 +} + +#endif +} + +#ifdef WIN32 +pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height, + int stride) +#else +pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height, + int stride) +#endif +{ +#ifdef WIN32 + if (dc) { + if (abs(stride) == (width * 4)) { + return surface_create(dc, format, width, height, (stride > 0)); + } + } +#endif + + return __surface_create_stride(format, width, height, stride); +} + +pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data, + pixman_format_code_t pixman_format, int width, + int height, int gross_pixels, int top_down) +{ + int stride; + pixman_image_t *surface = NULL; + + stride = (gross_pixels / height) * (PIXMAN_FORMAT_BPP (pixman_format) / 8); + + /* pixman requires strides to be 4-byte aligned */ + stride = SPICE_ALIGN(stride, 4); + + if (!top_down) { + stride = -stride; + } + + surface = surface_create_stride( +#ifdef WIN32 + canvas_data->dc, +#endif + pixman_format, width, height, stride); + canvas_data->out_surface = surface; + return surface; +} diff --git a/spice-common/common/canvas_utils.h b/spice-common/common/canvas_utils.h new file mode 100644 index 0000000..ef3f9c5 --- /dev/null +++ b/spice-common/common/canvas_utils.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_CANVAS_UTILS +#define _H_CANVAS_UTILS + +#ifdef WIN32 +#include +#endif + +#include +#include + +#include "pixman_utils.h" +#include "lz.h" + +SPICE_BEGIN_DECLS + +typedef struct PixmanData { +#ifdef WIN32 + HBITMAP bitmap; + HANDLE mutex; +#endif + uint8_t *data; + pixman_format_code_t format; +} PixmanData; + +void spice_pixman_image_set_format(pixman_image_t *image, + pixman_format_code_t format); +int spice_pixman_image_get_format(pixman_image_t *image, pixman_format_code_t *format); + + +#ifdef WIN32 +pixman_image_t *surface_create(HDC dc, pixman_format_code_t format, + int width, int height, int top_down); +#else +pixman_image_t *surface_create(pixman_format_code_t format, int width, int height, int top_down); +#endif + +#ifdef WIN32 +pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height, + int stride); +#else +pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height, + int stride); +#endif + + +typedef struct LzDecodeUsrData { +#ifdef WIN32 + HDC dc; +#endif + pixman_image_t *out_surface; +} LzDecodeUsrData; + + +pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data, + pixman_format_code_t pixman_format, int width, + int height, int gross_pixels, int top_down); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/client_demarshallers.h b/spice-common/common/client_demarshallers.h new file mode 100644 index 0000000..af095a0 --- /dev/null +++ b/spice-common/common/client_demarshallers.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef _H_DEMARSHAL +#define _H_DEMARSHAL + +#include +#include + +SPICE_BEGIN_DECLS + +typedef void (*message_destructor_t)(uint8_t *message); +typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, + size_t *size_out, message_destructor_t *free_message); + +spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type); +spice_parse_channel_func_t spice_get_server_channel_parser1(uint32_t channel, unsigned int *max_message_type); + +SPICE_END_DECLS + +#endif + diff --git a/spice-common/common/client_marshallers.h b/spice-common/common/client_marshallers.h new file mode 100644 index 0000000..728987e --- /dev/null +++ b/spice-common/common/client_marshallers.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_MARSHALLERS +#define _H_MARSHALLERS + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "marshaller.h" +#include "messages.h" + +SPICE_BEGIN_DECLS + +typedef struct { + void (*msg_SpiceMsgEmpty)(SpiceMarshaller *m, SpiceMsgEmpty *msg); + void (*msg_SpiceMsgData)(SpiceMarshaller *m, SpiceMsgData *msg); + void (*msgc_ack_sync)(SpiceMarshaller *m, SpiceMsgcAckSync *msg); + void (*msgc_pong)(SpiceMarshaller *m, SpiceMsgPing *msg); + void (*msgc_disconnecting)(SpiceMarshaller *m, SpiceMsgDisconnect *msg); + void (*msgc_main_client_info)(SpiceMarshaller *m, SpiceMsgcClientInfo *msg); + void (*msgc_main_mouse_mode_request)(SpiceMarshaller *m, SpiceMsgcMainMouseModeRequest *msg); + void (*msgc_main_agent_start)(SpiceMarshaller *m, SpiceMsgcMainAgentStart *msg); + void (*msgc_main_agent_token)(SpiceMarshaller *m, SpiceMsgcMainAgentTokens *msg); + void (*msgc_main_migrate_dst_do_seamless)(SpiceMarshaller *m, SpiceMsgcMainMigrateDstDoSeamless *msg); + void (*msgc_display_init)(SpiceMarshaller *m, SpiceMsgcDisplayInit *msg); + void (*msgc_display_stream_report)(SpiceMarshaller *m, SpiceMsgcDisplayStreamReport *msg); + void (*msgc_display_gl_draw_done)(SpiceMarshaller *m, SpiceMsgcDisplayGlDrawDone *msg); + void (*msgc_inputs_key_down)(SpiceMarshaller *m, SpiceMsgcKeyDown *msg); + void (*msgc_inputs_key_up)(SpiceMarshaller *m, SpiceMsgcKeyUp *msg); + void (*msgc_inputs_key_modifiers)(SpiceMarshaller *m, SpiceMsgcKeyModifiers *msg); + void (*msgc_inputs_mouse_motion)(SpiceMarshaller *m, SpiceMsgcMouseMotion *msg); + void (*msgc_inputs_mouse_position)(SpiceMarshaller *m, SpiceMsgcMousePosition *msg); + void (*msgc_inputs_mouse_press)(SpiceMarshaller *m, SpiceMsgcMousePress *msg); + void (*msgc_inputs_mouse_release)(SpiceMarshaller *m, SpiceMsgcMouseRelease *msg); + void (*msgc_record_data)(SpiceMarshaller *m, SpiceMsgcRecordPacket *msg); + void (*msgc_record_mode)(SpiceMarshaller *m, SpiceMsgcRecordMode *msg); + void (*msgc_record_start_mark)(SpiceMarshaller *m, SpiceMsgcRecordStartMark *msg); + void (*msgc_tunnel_service_add)(SpiceMarshaller *m, SpiceMsgcTunnelAddGenericService *msg, SpiceMarshaller **name_out, SpiceMarshaller **description_out); + void (*msgc_tunnel_service_remove)(SpiceMarshaller *m, SpiceMsgcTunnelRemoveService *msg); + void (*msgc_tunnel_socket_open_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenAck *msg); + void (*msgc_tunnel_socket_open_nack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenNack *msg); + void (*msgc_tunnel_socket_fin)(SpiceMarshaller *m, SpiceMsgcTunnelSocketFin *msg); + void (*msgc_tunnel_socket_closed)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosed *msg); + void (*msgc_tunnel_socket_closed_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosedAck *msg); + void (*msgc_tunnel_socket_data)(SpiceMarshaller *m, SpiceMsgcTunnelSocketData *msg); + void (*msgc_tunnel_socket_token)(SpiceMarshaller *m, SpiceMsgcTunnelSocketTokens *msg); +#ifdef USE_SMARTCARD + void (*msgc_smartcard_atr)(SpiceMarshaller *m, VSCMsgATR *msg); + void (*msgc_smartcard_error)(SpiceMarshaller *m, VSCMsgError *msg); + void (*msgc_smartcard_header)(SpiceMarshaller *m, VSCMsgHeader *msg); + void (*msgc_smartcard_data)(SpiceMarshaller *m, SpiceMsgcSmartcard *msg, SpiceMarshaller **reader_name_out); + void (*msgc_smartcard_reader_add)(SpiceMarshaller *m, VSCMsgReaderAdd *msg); +#endif + void (*msgc_port_event)(SpiceMarshaller *m, SpiceMsgcPortEvent *msg); + void (*msgc_display_preferred_compression)(SpiceMarshaller *m, SpiceMsgcDisplayPreferredCompression *msg); +} SpiceMessageMarshallers; + +SpiceMessageMarshallers *spice_message_marshallers_get(void); +SpiceMessageMarshallers *spice_message_marshallers_get1(void); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/draw.h b/spice-common/common/draw.h new file mode 100644 index 0000000..5ce56e7 --- /dev/null +++ b/spice-common/common/draw.h @@ -0,0 +1,305 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holder 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 COPYRIGHT HOLDER 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 COPYRIGHT + HOLDER 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 _H_SPICE_DRAW +#define _H_SPICE_DRAW + +#include +#include +#include +#include "mem.h" + +SPICE_BEGIN_DECLS + +#define SPICE_GET_ADDRESS(addr) ((void *)(uintptr_t)(addr)) +#define SPICE_SET_ADDRESS(addr, val) ((addr) = (uintptr_t)(val)) + +typedef int32_t SPICE_FIXED28_4; + +typedef struct SpicePointFix { + SPICE_FIXED28_4 x; + SPICE_FIXED28_4 y; +} SpicePointFix; + +typedef struct SpicePoint { + int32_t x; + int32_t y; +} SpicePoint; + +typedef struct SpicePoint16 { + int16_t x; + int16_t y; +} SpicePoint16; + +typedef struct SpiceRect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +} SpiceRect; + +typedef struct SpicePathSeg { + uint32_t flags; + uint32_t count; + SpicePointFix points[0]; +} SpicePathSeg; + +typedef struct SpicePath { + uint32_t num_segments; + SpicePathSeg *segments[0]; +} SpicePath; + +typedef struct SpiceClipRects { + uint32_t num_rects; + SpiceRect rects[0]; +} SpiceClipRects; + +typedef struct SpiceClip { + uint8_t type; + SpiceClipRects *rects; +} SpiceClip; + +typedef struct SpicePalette { + uint64_t unique; + uint16_t num_ents; + uint32_t ents[0]; +} SpicePalette; + +#define SPICE_SURFACE_FMT_DEPTH(_d) ((_d) & 0x3f) + +typedef struct SpiceImageDescriptor { + uint64_t id; + uint8_t type; + uint8_t flags; + uint32_t width; + uint32_t height; +} SpiceImageDescriptor; + +typedef struct SpiceBitmap { + uint8_t format; + uint8_t flags; + uint32_t x; + uint32_t y; + uint32_t stride; + SpicePalette *palette; + uint64_t palette_id; + SpiceChunks *data; +} SpiceBitmap; + +typedef struct SpiceSurface { + uint32_t surface_id; +} SpiceSurface; + +typedef struct SpiceQUICData { + uint32_t data_size; + SpiceChunks *data; +} SpiceQUICData, SpiceLZRGBData, SpiceJPEGData, SpiceLZ4Data; + +typedef struct SpiceLZPLTData { + uint8_t flags; + uint32_t data_size; + SpicePalette *palette; + uint64_t palette_id; + SpiceChunks *data; +} SpiceLZPLTData; + +typedef struct SpiceZlibGlzRGBData { + uint32_t glz_data_size; + uint32_t data_size; + SpiceChunks *data; +} SpiceZlibGlzRGBData; + +typedef struct SpiceJPEGAlphaData { + uint8_t flags; + uint32_t jpeg_size; + uint32_t data_size; + SpiceChunks *data; +} SpiceJPEGAlphaData; + + +typedef struct SpiceImage { + SpiceImageDescriptor descriptor; + union { + SpiceBitmap bitmap; + SpiceQUICData quic; + SpiceSurface surface; + SpiceLZRGBData lz_rgb; + SpiceLZPLTData lz_plt; + SpiceJPEGData jpeg; + SpiceLZ4Data lz4; + SpiceZlibGlzRGBData zlib_glz; + SpiceJPEGAlphaData jpeg_alpha; + } u; +} SpiceImage; + +typedef struct SpicePattern { + SpiceImage *pat; + SpicePoint pos; +} SpicePattern; + +typedef struct SpiceBrush { + uint32_t type; + union { + uint32_t color; + SpicePattern pattern; + } u; +} SpiceBrush; + +typedef struct SpiceQMask { + uint8_t flags; + SpicePoint pos; + SpiceImage *bitmap; +} SpiceQMask; + +typedef struct SpiceFill { + SpiceBrush brush; + uint16_t rop_descriptor; + SpiceQMask mask; +} SpiceFill; + +typedef struct SpiceOpaque { + SpiceImage *src_bitmap; + SpiceRect src_area; + SpiceBrush brush; + uint16_t rop_descriptor; + uint8_t scale_mode; + SpiceQMask mask; +} SpiceOpaque; + +typedef struct SpiceCopy { + SpiceImage *src_bitmap; + SpiceRect src_area; + uint16_t rop_descriptor; + uint8_t scale_mode; + SpiceQMask mask; +} SpiceCopy, SpiceBlend; + +typedef struct SpiceTransparent { + SpiceImage *src_bitmap; + SpiceRect src_area; + uint32_t src_color; + uint32_t true_color; +} SpiceTransparent; + +typedef struct SpiceAlphaBlend { + uint16_t alpha_flags; + uint8_t alpha; + SpiceImage *src_bitmap; + SpiceRect src_area; +} SpiceAlphaBlend; + +typedef struct SpiceRop3 { + SpiceImage *src_bitmap; + SpiceRect src_area; + SpiceBrush brush; + uint8_t rop3; + uint8_t scale_mode; + SpiceQMask mask; +} SpiceRop3; + +/* Given in 16.16 fixed point */ +typedef struct SpiceTransform { + uint32_t t00; + uint32_t t01; + uint32_t t02; + uint32_t t10; + uint32_t t11; + uint32_t t12; +} SpiceTransform; + +typedef struct SpiceComposite { + uint32_t flags; + SpiceImage *src_bitmap; + SpiceImage *mask_bitmap; + SpiceTransform src_transform; + SpiceTransform mask_transform; + SpicePoint16 src_origin; + SpicePoint16 mask_origin; +} SpiceComposite; + +typedef struct SpiceBlackness { + SpiceQMask mask; +} SpiceBlackness, SpiceInvers, SpiceWhiteness; + +typedef struct SpiceLineAttr { + uint8_t flags; + uint8_t style_nseg; + SPICE_FIXED28_4 *style; +} SpiceLineAttr; + +typedef struct SpiceStroke { + SpicePath *path; + SpiceLineAttr attr; + SpiceBrush brush; + uint16_t fore_mode; + uint16_t back_mode; +} SpiceStroke; + +typedef struct SpiceRasterGlyph { + SpicePoint render_pos; + SpicePoint glyph_origin; + uint16_t width; + uint16_t height; + uint8_t data[0]; +} SpiceRasterGlyph; + +typedef struct SpiceString { + uint16_t length; + uint16_t flags; + SpiceRasterGlyph *glyphs[0]; +} SpiceString; + +typedef struct SpiceText { + SpiceString *str; + SpiceRect back_area; + SpiceBrush fore_brush; + SpiceBrush back_brush; + uint16_t fore_mode; + uint16_t back_mode; +} SpiceText; + +typedef struct SpiceCursorHeader { + uint64_t unique; + uint16_t type; + uint16_t width; + uint16_t height; + uint16_t hot_spot_x; + uint16_t hot_spot_y; +} SpiceCursorHeader; + +static inline int spice_image_descriptor_is_lossy(const SpiceImageDescriptor *descriptor) +{ + return descriptor->type == SPICE_IMAGE_TYPE_JPEG || + descriptor->type == SPICE_IMAGE_TYPE_JPEG_ALPHA; +} + +SPICE_END_DECLS + +#endif /* _H_SPICE_DRAW */ diff --git a/spice-common/common/gdi_canvas.c b/spice-common/common/gdi_canvas.c new file mode 100644 index 0000000..fcc5fc9 --- /dev/null +++ b/spice-common/common/gdi_canvas.c @@ -0,0 +1,1860 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#ifdef __MINGW32__ +#undef HAVE_STDLIB_H +#endif +#include +#endif + +#include +#include +#include "gdi_canvas.h" +#define GDI_CANVAS +#include "canvas_base.c" +#include "rop3.h" +#include "rect.h" +#include "region.h" +#include "threads.h" + +typedef struct GdiCanvas GdiCanvas; + +struct GdiCanvas { + CanvasBase base; + HDC dc; + RecurciveMutex* lock; +}; + + +struct BitmapData { + HBITMAP hbitmap; + HBITMAP prev_hbitmap; + SpicePoint pos; + uint8_t flags; + HDC dc; + int cache; + int from_surface; +}; + +#define _rop3_brush 0xf0 +#define _rop3_src 0xcc +#define _rop3_dest 0xaa + +uint32_t raster_ops[] = { + 0x00000042, + 0x00010289, + 0x00020C89, + 0x000300AA, + 0x00040C88, + 0x000500A9, + 0x00060865, + 0x000702C5, + 0x00080F08, + 0x00090245, + 0x000A0329, + 0x000B0B2A, + 0x000C0324, + 0x000D0B25, + 0x000E08A5, + 0x000F0001, + 0x00100C85, + 0x001100A6, + 0x00120868, + 0x001302C8, + 0x00140869, + 0x001502C9, + 0x00165CCA, + 0x00171D54, + 0x00180D59, + 0x00191CC8, + 0x001A06C5, + 0x001B0768, + 0x001C06CA, + 0x001D0766, + 0x001E01A5, + 0x001F0385, + 0x00200F09, + 0x00210248, + 0x00220326, + 0x00230B24, + 0x00240D55, + 0x00251CC5, + 0x002606C8, + 0x00271868, + 0x00280369, + 0x002916CA, + 0x002A0CC9, + 0x002B1D58, + 0x002C0784, + 0x002D060A, + 0x002E064A, + 0x002F0E2A, + 0x0030032A, + 0x00310B28, + 0x00320688, + 0x00330008, + 0x003406C4, + 0x00351864, + 0x003601A8, + 0x00370388, + 0x0038078A, // PSDPoax + 0x00390604, // SPDnox + 0x003A0644, // SPDSxox + 0x003B0E24, // SPDnoan + 0x003C004A, // PSx + 0x003D18A4, // SPDSonox + 0x003E1B24, // SPDSnaox + 0x003F00EA, // PSan + 0x00400F0A, // PSDnaa + 0x00410249, // DPSxon + 0x00420D5D, // SDxPDxa + 0x00431CC4, // SPDSanaxn + 0x00440328, // SDna SRCERASE + 0x00450B29, // DPSnaon + 0x004606C6, // DSPDaox + 0x0047076A, // PSDPxaxn + 0x00480368, // SDPxa + 0x004916C5, // PDSPDaoxxn + 0x004A0789, // DPSDoax + 0x004B0605, // PDSnox + 0x004C0CC8, // SDPana + 0x004D1954, // SSPxDSxoxn + 0x004E0645, // PDSPxox + 0x004F0E25, // PDSnoan + 0x00500325, // PDna + 0x00510B26, // DSPnaon + 0x005206C9, // DPSDaox + 0x00530764, // SPDSxaxn + 0x005408A9, // DPSonon + 0x00550009, // Dn DSTINVERT + 0x005601A9, // DPSox + 0x00570389, // DPSoan + 0x00580785, // PDSPoax + 0x00590609, // DPSnox + 0x005A0049, // DPx PATINVERT + 0x005B18A9, // DPSDonox + 0x005C0649, // DPSDxox + 0x005D0E29, // DPSnoan + 0x005E1B29, // DPSDnaox + 0x005F00E9, // DPan + 0x00600365, // PDSxa + 0x006116C6, // DSPDSaoxxn + 0x00620786, // DSPDoax + 0x00630608, // SDPnox + 0x00640788, // SDPSoax + 0x00650606, // DSPnox + 0x00660046, // DSx SRCINVERT + 0x006718A8, // SDPSonox + 0x006858A6, // DSPDSonoxxn + 0x00690145, // PDSxxn + 0x006A01E9, // DPSax + 0x006B178A, // PSDPSoaxxn + 0x006C01E8, // SDPax + 0x006D1785, // PDSPDoaxxn + 0x006E1E28, // SDPSnoax + 0x006F0C65, // PDSxnan + 0x00700CC5, // PDSana + 0x00711D5C, // SSDxPDxaxn + 0x00720648, // SDPSxox + 0x00730E28, // SDPnoan + 0x00740646, // DSPDxox + 0x00750E26, // DSPnoan + 0x00761B28, // SDPSnaox + 0x007700E6, // DSan + 0x007801E5, // PDSax + 0x00791786, // DSPDSoaxxn + 0x007A1E29, // DPSDnoax + 0x007B0C68, // SDPxnan + 0x007C1E24, // SPDSnoax + 0x007D0C69, // DPSxnan + 0x007E0955, // SPxDSxo + 0x007F03C9, // DPSaan + 0x008003E9, // DPSaa + 0x00810975, // SPxDSxon + 0x00820C49, // DPSxna + 0x00831E04, // SPDSnoaxn + 0x00840C48, // SDPxna + 0x00851E05, // PDSPnoaxn + 0x008617A6, // DSPDSoaxx + 0x008701C5, // PDSaxn + 0x008800C6, // DSa SRCAND + 0x00891B08, // SDPSnaoxn + 0x008A0E06, // DSPnoa + 0x008B0666, // DSPDxoxn + 0x008C0E08, // SDPnoa + 0x008D0668, // SDPSxoxn + 0x008E1D7C, // SSDxPDxax + 0x008F0CE5, // PDSanan + 0x00900C45, // PDSxna + 0x00911E08, // SDPSnoaxn + 0x009217A9, // DPSDPoaxx + 0x009301C4, // SPDaxn + 0x009417AA, // PSDPSoaxx + 0x009501C9, // DPSaxn + 0x00960169, // DPSxx + 0x0097588A, // PSDPSonoxx + 0x00981888, // SDPSonoxn + 0x00990066, // DSxn + 0x009A0709, // DPSnax + 0x009B07A8, // SDPSoaxn + 0x009C0704, // SPDnax + 0x009D07A6, // DSPDoaxn + 0x009E16E6, // DSPDSaoxx + 0x009F0345, // PDSxan + 0x00A000C9, // DPa + 0x00A11B05, // PDSPnaoxn + 0x00A20E09, // DPSnoa + 0x00A30669, // DPSDxoxn + 0x00A41885, // PDSPonoxn + 0x00A50065, // PDxn + 0x00A60706, // DSPnax + 0x00A707A5, // PDSPoaxn + 0x00A803A9, // DPSoa + 0x00A90189, // DPSoxn + 0x00AA0029, // D + 0x00AB0889, // DPSono + 0x00AC0744, // SPDSxax + 0x00AD06E9, // DPSDaoxn + 0x00AE0B06, // DSPnao + 0x00AF0229, // DPno + 0x00B00E05, // PDSnoa + 0x00B10665, // PDSPxoxn + 0x00B21974, // SSPxDSxox + 0x00B30CE8, // SDPanan + 0x00B4070A, // PSDnax + 0x00B507A9, // DPSDoaxn + 0x00B616E9, // DPSDPaoxx + 0x00B70348, // SDPxan + 0x00B8074A, // PSDPxax + 0x00B906E6, // DSPDaoxn + 0x00BA0B09, // DPSnao + 0x00BB0226, // DSno MERGEPAINT + 0x00BC1CE4, // SPDSanax + 0x00BD0D7D, // SDxPDxan + 0x00BE0269, // DPSxo + 0x00BF08C9, // DPSano + 0x00C000CA, // PSa MERGECOPY + 0x00C11B04, // SPDSnaoxn + 0x00C21884, // SPDSonoxn + 0x00C3006A, // PSxn + 0x00C40E04, // SPDnoa + 0x00C50664, // SPDSxoxn + 0x00C60708, // SDPnax + 0x00C707AA, // PSDPoaxn + 0x00C803A8, // SDPoa + 0x00C90184, // SPDoxn + 0x00CA0749, // DPSDxax + 0x00CB06E4, // SPDSaoxn + 0x00CC0020, // S SRCCOPY + 0x00CD0888, // SDPono + 0x00CE0B08, // SDPnao + 0x00CF0224, // SPno + 0x00D00E0A, // PSDnoa + 0x00D1066A, // PSDPxoxn + 0x00D20705, // PDSnax + 0x00D307A4, // SPDSoaxn + 0x00D41D78, // SSPxPDxax + 0x00D50CE9, // DPSanan + 0x00D616EA, // PSDPSaoxx + 0x00D70349, // DPSxan + 0x00D80745, // PDSPxax + 0x00D906E8, // SDPSaoxn + 0x00DA1CE9, // DPSDanax + 0x00DB0D75, // SPxDSxan + 0x00DC0B04, // SPDnao + 0x00DD0228, // SDno + 0x00DE0268, // SDPxo + 0x00DF08C8, // SDPano + 0x00E003A5, // PDSoa + 0x00E10185, // PDSoxn + 0x00E20746, // DSPDxax + 0x00E306EA, // PSDPaoxn + 0x00E40748, // SDPSxax + 0x00E506E5, // PDSPaoxn + 0x00E61CE8, // SDPSanax + 0x00E70D79, // SPxPDxan + 0x00E81D74, // SSPxDSxax + 0x00E95CE6, // DSPDSanaxxn + 0x00EA02E9, // DPSao + 0x00EB0849, // DPSxno + 0x00EC02E8, // SDPao + 0x00ED0848, // SDPxno + 0x00EE0086, // DSo SRCPAINT + 0x00EF0A08, // SDPnoo + 0x00F00021, // P PATCOPY + 0x00F10885, // PDSono + 0x00F20B05, // PDSnao + 0x00F3022A, // PSno + 0x00F40B0A, // PSDnao + 0x00F50225, // PDno + 0x00F60265, // PDSxo + 0x00F708C5, // PDSano + 0x00F802E5, // PDSao + 0x00F90845, // PDSxno + 0x00FA0089, // DPo + 0x00FB0A09, // DPSnoo PATPAINT + 0x00FC008A, // PSo + 0x00FD0A0A, // PSDnoo + 0x00FE02A9, // DPSoo + 0x00FF0062 // 1 WHITENESS +}; + +static void set_path(GdiCanvas *canvas, SpicePath *s) +{ + unsigned int i; + + for (i = 0; i < s->num_segments; i++) { + SpicePathSeg* seg = s->segments[i]; + SpicePointFix* point = seg->points; + SpicePointFix* end_point = point + seg->count; + + if (seg->flags & SPICE_PATH_BEGIN) { + BeginPath(canvas->dc); + if (!MoveToEx(canvas->dc, (int)fix_to_double(point->x), (int)fix_to_double(point->y), + NULL)) { + spice_critical("MoveToEx failed"); + return; + } + point++; + } + + if (seg->flags & SPICE_PATH_BEZIER) { + spice_return_if_fail((point - end_point) % 3 == 0); + for (; point + 2 < end_point; point += 3) { + POINT points[3]; + + points[0].x = (int)fix_to_double(point[0].x); + points[0].y = (int)fix_to_double(point[0].y); + points[1].x = (int)fix_to_double(point[1].x); + points[1].y = (int)fix_to_double(point[1].y); + points[2].x = (int)fix_to_double(point[2].x); + points[2].y = (int)fix_to_double(point[2].y); + if (!PolyBezierTo(canvas->dc, points, 3)) { + spice_critical("PolyBezierTo failed"); + return; + } + } + } else { + for (; point < end_point; point++) { + if (!LineTo(canvas->dc, (int)fix_to_double(point->x), + (int)fix_to_double(point->y))) { + spice_critical("LineTo failed"); + } + } + } + + if (seg->flags & SPICE_PATH_END) { + + if (seg->flags & SPICE_PATH_CLOSE) { + if (!CloseFigure(canvas->dc)) { + spice_critical("CloseFigure failed"); + } + } + + if (!EndPath(canvas->dc)) { + spice_critical("EndPath failed"); + } + } + + } +} + +static void set_scale_mode(GdiCanvas *canvas, uint8_t scale_mode) +{ + if (scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE) { + SetStretchBltMode(canvas->dc, HALFTONE); + } else if (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) { + SetStretchBltMode(canvas->dc, COLORONCOLOR); + } else { + spice_critical("Unknown ScaleMode"); + } +} + +static void set_clip(GdiCanvas *canvas, SpiceClip *clip) +{ + switch (clip->type) { + case SPICE_CLIP_TYPE_NONE: + if (SelectClipRgn(canvas->dc, NULL) == ERROR) { + spice_critical("SelectClipRgn failed"); + } + break; + case SPICE_CLIP_TYPE_RECTS: { + uint32_t n = clip->rects->num_rects; + + SpiceRect *now = clip->rects->rects; + SpiceRect *end = now + n; + + if (now < end) { + HRGN main_hrgn; + + main_hrgn = CreateRectRgn(now->left, now->top, now->right, now->bottom); + if (!main_hrgn) { + return; + } + now++; + for (; now < end; now++) { + HRGN combaine_hrgn; + combaine_hrgn = CreateRectRgn(now->left, now->top, now->right, + now->bottom); + if (!combaine_hrgn) { + spice_critical("Unable to CreateRectRgn"); + DeleteObject(main_hrgn); + return; + } + if (CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR) == ERROR) { + spice_critical("Unable to CombineRgn"); + DeleteObject(combaine_hrgn); + return; + } + DeleteObject(combaine_hrgn); + } + if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) { + spice_critical("Unable to SelectClipRgn"); + } + DeleteObject(main_hrgn); + } + break; + } + default: + spice_warn_if_reached(); + return; + } +} + +static void copy_bitmap(const uint8_t *src_image, int height, int src_stride, + uint8_t *dest_bitmap, int dest_stride) +{ + int copy_width = MIN(dest_stride, src_stride); + int y = 0; + + spice_return_if_fail(dest_stride >= 0 && src_stride >= 0); + + while (y < height) { + memcpy(dest_bitmap, src_image, copy_width); + src_image += src_stride; + dest_bitmap += dest_stride; + y++; + } +} + +static void copy_bitmap_alpha(const uint8_t *src_alpha, int height, int width, int src_stride, + uint8_t *dest_bitmap, int dest_stride, int alpha_bits_size) +{ + int y = 0; + uint8_t i_offset; + int i_count = 0; + int i = 0; + + if (alpha_bits_size == 1) { + i_offset = 1; + } else { + i_offset = 8; + } + + + while (y < height) { + int x; + + for (x = 0; x < width; ++x) { + uint8_t alphaval; + double alpha; + + alphaval = src_alpha[i]; + alphaval = alphaval >> (i_count * i_offset); + alphaval &= ((uint8_t)0xff >> (8 - i_offset)); + alphaval = ((255 * alphaval) / ((uint8_t)0xff >> (8 - i_offset))); + + dest_bitmap[x * 4 + 3] = alphaval; + alpha = (double)alphaval / 0xff; + dest_bitmap[x * 4 + 2] = (uint8_t)(alpha * dest_bitmap[x * 4 + 2]); + dest_bitmap[x * 4 + 1] = (uint8_t)(alpha * dest_bitmap[x * 4 + 1]); + dest_bitmap[x * 4] = (uint8_t)(alpha * dest_bitmap[x * 4]); + + i_count++; + if (i_count == (8 / i_offset)) { + i++; + i_count = 0; + } + } + + dest_bitmap += width * 4; + i = 0; + src_alpha += src_stride; + i_count = 0; + y++; + } +} + +static uint8_t *create_bitmap(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc, + const uint8_t *bitmap_data, int width, int height, + int stride, int bits, int rotate) +{ + uint8_t *data; + const uint8_t *src_data; + uint32_t nstride; + struct { + BITMAPINFO inf; + RGBQUAD palette[255]; + } bitmap_info; + + memset(&bitmap_info, 0, sizeof(bitmap_info)); + bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); + bitmap_info.inf.bmiHeader.biWidth = width; + if (stride < 0) { + bitmap_info.inf.bmiHeader.biHeight = height; + } else { + bitmap_info.inf.bmiHeader.biHeight = -height; + } + + if (rotate) { + bitmap_info.inf.bmiHeader.biHeight = -bitmap_info.inf.bmiHeader.biHeight; + } + + bitmap_info.inf.bmiHeader.biPlanes = 1; + bitmap_info.inf.bmiHeader.biBitCount = bits; + bitmap_info.inf.bmiHeader.biCompression = BI_RGB; + + *dc = create_compatible_dc(); + if (!*dc) { + spice_critical("create_compatible_dc() failed"); + return NULL; + } + + *bitmap = CreateDIBSection(*dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0); + if (!*bitmap) { + spice_critical("Unable to CreateDIBSection"); + DeleteDC(*dc); + return NULL; + } + *prev_bitmap = (HBITMAP)SelectObject(*dc, *bitmap); + + if (stride < 0) { + src_data = bitmap_data - (height - 1) * -stride; + } else { + src_data = bitmap_data; + } + + switch (bits) { + case 1: + nstride = SPICE_ALIGN(width, 32) / 8; + break; + case 8: + nstride = SPICE_ALIGN(width, 4); + break; + case 16: + nstride = SPICE_ALIGN(width * 2, 4); + break; + case 32: + nstride = width * 4; + break; + default: + spice_warn_if_reached(); + return NULL; + } + + if (bitmap_data) { + if (stride < 0) { + copy_bitmap(src_data, height, -stride, data, nstride); + } else { + copy_bitmap(src_data, height, stride, data, nstride); + } + } + + return data; +} + +static uint8_t *create_bitmap_from_pixman(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc, + pixman_image_t *surface, int rotate) +{ + return create_bitmap(bitmap, prev_bitmap, dc, + (uint8_t*)pixman_image_get_data(surface), + pixman_image_get_width(surface), + pixman_image_get_height(surface), + pixman_image_get_stride(surface), + spice_pixman_image_get_bpp(surface), + rotate); +} + + +static void release_bitmap(HDC dc, HBITMAP bitmap, HBITMAP prev_bitmap, int cache) +{ + bitmap = (HBITMAP)SelectObject(dc, prev_bitmap); + if (!cache) { + DeleteObject(bitmap); + } + DeleteDC(dc); +} + +static inline uint8_t get_converted_color(uint8_t color) +{ + uint8_t msb; + + msb = color & 0xE0; + msb = msb >> 5; + color |= msb; + return color; +} + +static inline COLORREF get_color_ref(GdiCanvas *canvas, uint32_t color) +{ + int shift = canvas->base.color_shift == 8 ? 0 : 3; + uint8_t r, g, b; + + b = (color & canvas->base.color_mask); + color >>= canvas->base.color_shift; + g = (color & canvas->base.color_mask); + color >>= canvas->base.color_shift; + r = (color & canvas->base.color_mask); + if (shift) { + r = get_converted_color(r << shift); + g = get_converted_color(g << shift); + b = get_converted_color(b << shift); + } + return RGB(r, g, b); +} + +static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush, RecurciveMutex **brush_lock) +{ + HBRUSH hbrush; + + *brush_lock = NULL; + + switch (brush->type) { + case SPICE_BRUSH_TYPE_SOLID: + if (!(hbrush = CreateSolidBrush(get_color_ref(canvas, brush->u.color)))) { + spice_critical("CreateSolidBrush failed"); + return NULL; + } + return hbrush; + case SPICE_BRUSH_TYPE_PATTERN: { + GdiCanvas *gdi_surface = NULL; + HBRUSH hbrush; + pixman_image_t *surface = NULL; + HDC dc; + HBITMAP bitmap; + HBITMAP prev_bitmap; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat); + if (gdi_surface) { + bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP); + if (!bitmap) { + spice_critical("GetCurrentObject failed"); + return NULL; + } + *brush_lock = gdi_surface->lock; + } else { + surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE); + if (!create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, surface, 0)) { + spice_critical("create_bitmap failed"); + return NULL; + } + } + + if (!(hbrush = CreatePatternBrush(bitmap))) { + spice_critical("CreatePatternBrush failed"); + return NULL; + } + + if (!gdi_surface) { + release_bitmap(dc, bitmap, prev_bitmap, 0); + pixman_image_unref(surface); + } + return hbrush; + } + case SPICE_BRUSH_TYPE_NONE: + return NULL; + default: + spice_warn_if_reached(); + return NULL; + } +} + +static HBRUSH set_brush(HDC dc, HBRUSH hbrush, SpiceBrush *brush) +{ + switch (brush->type) { + case SPICE_BRUSH_TYPE_SOLID: { + return (HBRUSH)SelectObject(dc, hbrush); + } + case SPICE_BRUSH_TYPE_PATTERN: { + HBRUSH prev_hbrush; + prev_hbrush = (HBRUSH)SelectObject(dc, hbrush); + if (!SetBrushOrgEx(dc, brush->u.pattern.pos.x, brush->u.pattern.pos.y, NULL)) { + spice_critical("SetBrushOrgEx failed"); + return NULL; + } + return prev_hbrush; + } + default: + spice_warn_if_reached(); + return NULL; + } +} + +static void unset_brush(HDC dc, HBRUSH prev_hbrush) +{ + if (!prev_hbrush) { + return; + } + prev_hbrush = (HBRUSH)SelectObject(dc, prev_hbrush); + DeleteObject(prev_hbrush); +} + +uint8_t calc_rop3(uint16_t rop3_bits, int brush) +{ + uint8_t rop3 = 0; + uint8_t rop3_src = _rop3_src; + uint8_t rop3_dest = _rop3_dest; + uint8_t rop3_brush = _rop3_brush; + uint8_t rop3_src_brush; + + if (rop3_bits & SPICE_ROPD_INVERS_SRC) { + rop3_src = ~rop3_src; + } + if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) { + rop3_brush = ~rop3_brush; + } + if (rop3_bits & SPICE_ROPD_INVERS_DEST) { + rop3_dest = ~rop3_dest; + } + + if (brush) { + rop3_src_brush = rop3_brush; + } else { + rop3_src_brush = rop3_src; + } + + if (rop3_bits & SPICE_ROPD_OP_PUT) { + rop3 = rop3_src_brush; + } + if (rop3_bits & SPICE_ROPD_OP_OR) { + rop3 = rop3_src_brush | rop3_dest; + } + if (rop3_bits & SPICE_ROPD_OP_AND) { + rop3 = rop3_src_brush & rop3_dest; + } + if (rop3_bits & SPICE_ROPD_OP_XOR) { + rop3 = rop3_src_brush ^ rop3_dest; + } + if (rop3_bits & SPICE_ROPD_INVERS_RES) { + rop3 = ~rop3_dest; + } + + if (rop3_bits & SPICE_ROPD_OP_BLACKNESS || rop3_bits & SPICE_ROPD_OP_WHITENESS || + rop3_bits & SPICE_ROPD_OP_INVERS) { + spice_warning("invalid rop3 type"); + return 0; + } + return rop3; +} + +uint8_t calc_rop3_src_brush(uint16_t rop3_bits) +{ + uint8_t rop3 = 0; + uint8_t rop3_src = _rop3_src; + uint8_t rop3_brush = _rop3_brush; + + if (rop3_bits & SPICE_ROPD_INVERS_SRC) { + rop3_src = ~rop3_src; + } + if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) { + rop3_brush = ~rop3_brush; + } + + if (rop3_bits & SPICE_ROPD_OP_OR) { + rop3 = rop3_src | rop3_brush; + } + if (rop3_bits & SPICE_ROPD_OP_AND) { + rop3 = rop3_src & rop3_brush; + } + if (rop3_bits & SPICE_ROPD_OP_XOR) { + rop3 = rop3_src ^ rop3_brush; + } + + return rop3; +} + +static struct BitmapData get_mask_bitmap(struct GdiCanvas *canvas, struct SpiceQMask *mask) +{ + GdiCanvas *gdi_surface; + pixman_image_t *surface; + struct BitmapData bitmap; + PixmanData *pixman_data; + + bitmap.hbitmap = NULL; + if (!mask->bitmap) { + return bitmap; + } + + gdi_surface = (GdiCanvas *)canvas_get_surface_mask(&canvas->base, mask->bitmap); + if (gdi_surface) { + HBITMAP _bitmap; + + _bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP); + if (!_bitmap) { + spice_critical("GetCurrentObject failed"); + return bitmap; + } + bitmap.dc = gdi_surface->dc; + bitmap.hbitmap = _bitmap; + bitmap.prev_hbitmap = (HBITMAP)0; + bitmap.cache = 0; + bitmap.from_surface = 1; + } else { + + if (!(surface = canvas_get_mask(&canvas->base, mask, NULL))) { + return bitmap; + } + + pixman_data = (PixmanData *)pixman_image_get_destroy_data (surface); + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + bitmap.dc = create_compatible_dc(); + bitmap.prev_hbitmap = (HBITMAP)SelectObject(bitmap.dc, pixman_data->bitmap); + bitmap.hbitmap = pixman_data->bitmap; + ReleaseMutex(pixman_data->mutex); + bitmap.cache = 1; + } else if (!create_bitmap_from_pixman(&bitmap.hbitmap, &bitmap.prev_hbitmap, &bitmap.dc, + surface, 0)) { + bitmap.hbitmap = NULL; + } else { + bitmap.cache = 0; + } + + bitmap.from_surface = 0; + } + + bitmap.flags = mask->flags; + bitmap.pos = mask->pos; + + return bitmap; +} + +static void gdi_draw_bitmap(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + HDC src_dc, struct BitmapData *bitmapmask, uint32_t rop3_val) +{ + uint32_t rast_oper; + + rast_oper = raster_ops[rop3_val]; + + if (!bitmapmask || !bitmapmask->hbitmap) { + if ((dest->right - dest->left) == (src->right - src->left) && + (dest->bottom - dest->top) == (src->bottom - src->top)) { + if (!BitBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, src_dc, src->left, src->top, rast_oper)) { + spice_critical("BitBlt failed"); + return; + } + } else { + if (!StretchBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, src_dc, src->left, src->top, + src->right - src->left, src->bottom - src->top, rast_oper)) { + spice_critical("StretchBlt failed"); + return; + } + } + } else { + rast_oper = MAKEROP4(rast_oper, raster_ops[_rop3_dest]); + + if (!MaskBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, src_dc, src->left, src->top, + bitmapmask->hbitmap, bitmapmask->pos.x, bitmapmask->pos.y, + rast_oper)) { + spice_critical("MaskBlt failed"); + return; + } + } +} + +static void gdi_draw_bitmap_redrop(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + HDC src_dc, struct BitmapData *bitmapmask, + uint16_t rop, int brush) +{ + uint32_t rop3_val; + + rop3_val = calc_rop3(rop, brush); + gdi_draw_bitmap(dest_dc, src, dest, src_dc, bitmapmask, rop3_val); +} + +static void free_mask(struct BitmapData *bitmap) +{ + if (bitmap->hbitmap) { + if (!bitmap->from_surface) { + release_bitmap(bitmap->dc, bitmap->hbitmap, bitmap->prev_hbitmap, bitmap->cache); + } + } +} + +static void draw_str_mask_bitmap(struct GdiCanvas *canvas, + SpiceString *str, int n, SpiceRect *dest, + SpiceRect *src, SpiceBrush *brush) +{ + pixman_image_t *surface; + struct BitmapData bitmap; + SpicePoint pos; + int dest_stride; + uint8_t *bitmap_data; + HBRUSH prev_hbrush; + HBRUSH hbrush; + RecurciveMutex *brush_lock; + + bitmap.hbitmap = (HBITMAP)1; + if (!(surface = canvas_get_str_mask(&canvas->base, str, n, &pos))) { + spice_critical("unable to canvas_get_str_mask"); + return; + } + + bitmap.from_surface = 0; + bitmap.cache = 0; + bitmap_data = create_bitmap(&bitmap.hbitmap, &bitmap.prev_hbitmap, + &bitmap.dc, NULL, + pixman_image_get_width(surface), + pixman_image_get_height(surface), + pixman_image_get_stride(surface), 32, 0); + + if (!bitmap_data) { + return; + } + + bitmap.flags = 0; + bitmap.pos.x = 0; + bitmap.pos.y = 0; + + dest->left = pos.x; + dest->top = pos.y; + dest->right = pos.x + pixman_image_get_width(surface); + dest->bottom = pos.y + pixman_image_get_height(surface); + src->left = 0; + src->top = 0; + src->right = pixman_image_get_width(surface); + src->bottom = pixman_image_get_height(surface); + + dest_stride = pixman_image_get_width(surface); + switch (n) { + case 1: + dest_stride = dest_stride / 8; + break; + case 4: + dest_stride = dest_stride / 2; + break; + case 32: + dest_stride = dest_stride * 4; + break; + default: + spice_warn_if_reached(); + return; + } + dest_stride = dest_stride + 3; + dest_stride = dest_stride & ~3; + + hbrush = get_brush(canvas, brush, &brush_lock); + prev_hbrush = set_brush(bitmap.dc, hbrush, brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); + } else { + gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); + } + + unset_brush(bitmap.dc, prev_hbrush); + + copy_bitmap_alpha((uint8_t *)pixman_image_get_data(surface), + pixman_image_get_height(surface), + pixman_image_get_width(surface), + pixman_image_get_stride(surface), + bitmap_data, dest_stride, n); + + BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; + + RecurciveLock lock(*canvas->lock); + AlphaBlend(canvas->dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, bitmap.dc, src->left, src->top, + src->right - src->left, src->bottom - src->top, bf); + + free_mask(&bitmap); +} + +static void gdi_draw_image(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + pixman_image_t *image, struct BitmapData *bitmapmask, uint16_t rop, + int rotate) +{ + HDC dc; + HBITMAP bitmap; + HBITMAP prev_bitmap; + + create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); + + gdi_draw_bitmap_redrop(dest_dc, src, dest, dc, bitmapmask, rop, 0); + + release_bitmap(dc, bitmap, prev_bitmap, 0); +} + +static void gdi_draw_image_rop3(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + pixman_image_t *image, struct BitmapData *bitmapmask, uint8_t rop3, + int rotate) +{ + HDC dc; + HBITMAP bitmap; + HBITMAP prev_bitmap; + + create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); + + gdi_draw_bitmap(dest_dc, src, dest, dc, bitmapmask, rop3); + + release_bitmap(dc, bitmap, prev_bitmap, 0); +} + +static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + HBRUSH prev_hbrush; + HBRUSH brush; + struct BitmapData bitmapmask; + RecurciveMutex *brush_lock; + + RecurciveLock lock(*canvas->lock); + + brush = get_brush(canvas, &fill->brush, &brush_lock); + spice_return_if_fail(brush != NULL); + + bitmapmask = get_mask_bitmap(canvas, &fill->mask); + + set_clip(canvas, clip); + prev_hbrush = set_brush(canvas->dc, brush, &fill->brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, + fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); + } else { + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, + fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); + } + + free_mask(&bitmapmask); + unset_brush(canvas->dc, prev_hbrush); +} + +static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + GdiCanvas *gdi_surface; + pixman_image_t *surface; + struct BitmapData bitmapmask; + PixmanData *pixman_data; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, copy->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + bitmapmask = get_mask_bitmap(canvas, ©->mask); + set_scale_mode(canvas, copy->scale_mode); + set_clip(canvas, clip); + gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, gdi_surface->dc, + &bitmapmask, copy->rop_descriptor, 0); + } else { + surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE); + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, ©->mask); + set_scale_mode(canvas, copy->scale_mode); + set_clip(canvas, clip); + + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, dc, + &bitmapmask, copy->rop_descriptor, 0); + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + gdi_draw_image(canvas->dc, ©->src_area, bbox, surface, &bitmapmask, + copy->rop_descriptor, 0); + } + + pixman_image_unref(surface); + } + free_mask(&bitmapmask); +} + +static void gdi_canvas_put_image(SpiceCanvas *spice_canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data, + uint32_t src_width, uint32_t src_height, int src_stride, + const QRegion *clip) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + SpiceRect src; + src.top = 0; + src.bottom = src_height; + src.left = 0; + src.right = src_width; + int num_rects; + pixman_box32_t *rects; + + RecurciveLock lock(*canvas->lock); + set_scale_mode(canvas, SPICE_IMAGE_SCALE_MODE_NEAREST); + if (clip) { + rects = pixman_region32_rectangles((pixman_region32_t*)clip, &num_rects); + if (num_rects == 0) { + return; + } else { + HRGN main_hrgn; + int i; + + main_hrgn = CreateRectRgn(rects[0].x1, rects[0].y1, rects[0].x2, + rects[0].y2); + if (!main_hrgn) { + return; + } + + for (i = 1; i < num_rects; i++) { + HRGN combaine_hrgn; + + combaine_hrgn = CreateRectRgn(rects[i].x1, rects[i].y1, + rects[i].x2, + rects[i].y2); + if (!combaine_hrgn) { + spice_critical("CreateRectRgn failed"); + DeleteObject(main_hrgn); + return; + } + if (!CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR)) { + spice_critical("CombineRgn failed in put_image"); + return; + } + DeleteObject(combaine_hrgn); + } + if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) { + spice_critical("SelectClipRgn failed in put_image"); + DeleteObject(main_hrgn); + return; + } + DeleteObject(main_hrgn); + } + } else { + SelectClipRgn(canvas->dc, NULL); + } + + if (dc) { + gdi_draw_bitmap_redrop(canvas->dc, &src, dest, dc, + NULL, SPICE_ROPD_OP_PUT, 0); + } else { + pixman_image_t *image = pixman_image_create_bits(PIXMAN_a8r8g8b8, src_width, src_height, + (uint32_t *)src_data, src_stride); + gdi_draw_image(canvas->dc, &src, dest, image, NULL, SPICE_ROPD_OP_PUT, 0); + pixman_image_unref(image); + } +} + +static void gdi_draw_bitmap_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src, + const SpiceRect *dest, HDC src_dc, uint32_t color) +{ + TransparentBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, src_dc, src->left, src->top, + src->right - src->left, src->bottom - src->top, + RGB(((uint8_t*)&color)[2], ((uint8_t*)&color)[1], ((uint8_t*)&color)[0])); +} + +static void gdi_draw_image_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src, + const SpiceRect *dest, pixman_image_t *image, + uint32_t color, int rotate) +{ + HDC dc; + HBITMAP bitmap; + HBITMAP prev_bitmap; + + create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); + + gdi_draw_bitmap_transparent(canvas, dest_dc, src, dest, dc, color); + + release_bitmap(dc, bitmap, prev_bitmap, 0); +} + +static void gdi_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, + SpiceTransparent* transparent) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + GdiCanvas *gdi_surface; + pixman_image_t *surface; + PixmanData *pixman_data; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, transparent->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + set_clip(canvas, clip); + gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, + gdi_surface->dc, transparent->true_color); + } else { + surface = canvas_get_image(&canvas->base, transparent->src_bitmap, FALSE); + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + RecurciveLock lock(*canvas->lock); + set_clip(canvas, clip); + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, dc, + transparent->true_color); + + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + gdi_draw_image_transparent(canvas, canvas->dc, &transparent->src_area, bbox, surface, + transparent->true_color, 0); + } + + pixman_image_unref(surface); + } +} + +static void gdi_draw_bitmap_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + HDC src_dc, uint8_t alpha, int use_bitmap_alpha) +{ + BLENDFUNCTION bf; + + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = alpha; + + if (use_bitmap_alpha) { + bf.AlphaFormat = AC_SRC_ALPHA; + } else { + bf.AlphaFormat = 0; + } + + if (!AlphaBlend(dest_dc, dest->left, dest->top, dest->right - dest->left, + dest->bottom - dest->top, src_dc, src->left, src->top, + src->right - src->left, src->bottom - src->top, bf)) { + spice_critical("AlphaBlend failed"); + return; + } +} + +static void gdi_draw_image_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, + pixman_image_t *image, uint8_t alpha, + int rotate, int use_bitmap_alpha) +{ + HDC dc; + HBITMAP bitmap; + HBITMAP prev_bitmap; + + create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); + + gdi_draw_bitmap_alpha(dest_dc, src, dest, dc, alpha, use_bitmap_alpha); + + release_bitmap(dc, bitmap, prev_bitmap, 0); +} + +static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + GdiCanvas *gdi_surface; + pixman_image_t *surface; + PixmanData *pixman_data; + int use_bitmap_alpha; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, alpha_blend->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + set_clip(canvas, clip); + use_bitmap_alpha = alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA; + gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, gdi_surface->dc, + alpha_blend->alpha, use_bitmap_alpha); + } else { + surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap, TRUE); + use_bitmap_alpha = pixman_image_get_depth(surface) == 32; + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + + RecurciveLock lock(*canvas->lock); + set_clip(canvas, clip); + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, dc, alpha_blend->alpha, + use_bitmap_alpha); + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + gdi_draw_image_alpha(canvas->dc, &alpha_blend->src_area, bbox, surface, + alpha_blend->alpha, 0, use_bitmap_alpha); + } + + pixman_image_unref(surface); + } +} + +static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque) +{ + GdiCanvas *gdi_surface; + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + pixman_image_t *surface; + struct BitmapData bitmapmask; + PixmanData *pixman_data; + HBRUSH prev_hbrush; + HBRUSH hbrush; + uint8_t rop3; + RecurciveMutex *brush_lock; + + rop3 = calc_rop3_src_brush(opaque->rop_descriptor); + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, opaque->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + bitmapmask = get_mask_bitmap(canvas, &opaque->mask); + hbrush = get_brush(canvas, &opaque->brush, &brush_lock); + set_scale_mode(canvas, opaque->scale_mode); + set_clip(canvas, clip); + prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); + } else { + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); + } + unset_brush(canvas->dc, prev_hbrush); + } else { + surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE); + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, &opaque->mask); + hbrush = get_brush(canvas, &opaque->brush, &brush_lock); + set_scale_mode(canvas, opaque->scale_mode); + set_clip(canvas, clip); + prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush); + + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); + } else { + gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); + } + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0); + } else { + gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0); + } + } + unset_brush(canvas->dc, prev_hbrush); + pixman_image_unref(surface); + } + + free_mask(&bitmapmask); +} + +static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend) +{ + GdiCanvas *gdi_surface; + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + pixman_image_t *surface; + struct BitmapData bitmapmask; + PixmanData *pixman_data; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, blend->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + bitmapmask = get_mask_bitmap(canvas, &blend->mask); + set_scale_mode(canvas, blend->scale_mode); + set_clip(canvas, clip); + gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, gdi_surface->dc, + &bitmapmask, blend->rop_descriptor, 0); + } else { + surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE); + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, &blend->mask); + set_scale_mode(canvas, blend->scale_mode); + set_clip(canvas, clip); + + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, dc, + &bitmapmask, blend->rop_descriptor, 0); + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + gdi_draw_image(canvas->dc, &blend->src_area, bbox, surface, + &bitmapmask, blend->rop_descriptor, 0); + } + + pixman_image_unref(surface); + } + + free_mask(&bitmapmask); +} + +static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + struct BitmapData bitmapmask; + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, &blackness->mask); + set_clip(canvas, clip); + gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x0); + + free_mask(&bitmapmask); +} + +static void gdi_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + struct BitmapData bitmapmask; + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, &invers->mask); + set_clip(canvas, clip); + gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x55); + + free_mask(&bitmapmask); +} + +static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + struct BitmapData bitmapmask; + + RecurciveLock lock(*canvas->lock); + bitmapmask = get_mask_bitmap(canvas, &whiteness->mask); + set_clip(canvas, clip); + gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0xff); + + free_mask(&bitmapmask); +} + +static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3) +{ + GdiCanvas *gdi_surface; + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + pixman_image_t *surface; + struct BitmapData bitmapmask; + HBRUSH prev_hbrush; + HBRUSH hbrush; + PixmanData *pixman_data; + RecurciveMutex *brush_lock; + + gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, rop3->src_bitmap); + if (gdi_surface) { + RecurciveLock lock(*canvas->lock); + RecurciveLock s_lock(*gdi_surface->lock); + hbrush = get_brush(canvas, &rop3->brush, &brush_lock); + bitmapmask = get_mask_bitmap(canvas, &rop3->mask); + set_scale_mode(canvas, rop3->scale_mode); + set_clip(canvas, clip); + prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, + &bitmapmask, rop3->rop3); + } else { + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, + &bitmapmask, rop3->rop3); + } + unset_brush(canvas->dc, prev_hbrush); + } else { + surface = canvas_get_image(&canvas->base, rop3->src_bitmap, FALSE); + pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); + RecurciveLock lock(*canvas->lock); + hbrush = get_brush(canvas, &rop3->brush, &brush_lock); + bitmapmask = get_mask_bitmap(canvas, &rop3->mask); + set_scale_mode(canvas, rop3->scale_mode); + set_clip(canvas, clip); + prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush); + + if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { + HDC dc; + HBITMAP prev_bitmap; + + dc = create_compatible_dc(); + prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc, + &bitmapmask, rop3->rop3); + } else { + gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc, + &bitmapmask, rop3->rop3); + } + SelectObject(dc, prev_bitmap); + DeleteObject(dc); + ReleaseMutex(pixman_data->mutex); + } else { + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0); + } else { + gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0); + } + } + + unset_brush(canvas->dc, prev_hbrush); + pixman_image_unref(surface); + } + + free_mask(&bitmapmask); +} + +static void gdi_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + RecurciveLock lock(*canvas->lock); + + set_clip(canvas, clip); + + BitBlt(canvas->dc, bbox->left, bbox->top, bbox->right - bbox->left, + bbox->bottom - bbox->top, canvas->dc, src_pos->x, src_pos->y, SRCCOPY); +} + +static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + SpiceString *str; + RecurciveMutex *brush_lock; + + RecurciveLock lock(*canvas->lock); + set_clip(canvas, clip); + lock.unlock(); + + if (!rect_is_empty(&text->back_area)) { + HBRUSH prev_hbrush; + HBRUSH hbrush; + + RecurciveLock lock(*canvas->lock); + hbrush = get_brush(canvas, &text->back_brush, &brush_lock); + prev_hbrush = set_brush(canvas->dc, hbrush, &text->back_brush); + if (brush_lock) { + RecurciveLock b_lock(*brush_lock); + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, + text->back_mode, 1); + } else { + gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, + text->back_mode, 1); + } + unset_brush(canvas->dc, prev_hbrush); + } + + str = (SpiceString *)SPICE_GET_ADDRESS(text->str); + + if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) { + SpiceRect dest; + SpiceRect src; + + draw_str_mask_bitmap(canvas, str, 1, &dest, &src, &text->fore_brush); + } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) { + SpiceRect dest; + SpiceRect src; + + draw_str_mask_bitmap(canvas, str, 4, &dest, &src, &text->fore_brush); + } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) { + spice_warning("untested path A8 glyphs, doing nothing"); + if (0) { + SpiceRect dest; + SpiceRect src; + + draw_str_mask_bitmap(canvas, str, 8, &dest, &src, &text->fore_brush); + } + } else { + spice_warning("untested path vector glyphs, doing nothing"); + if (0) { + } + } +} + +static uint32_t *gdi_get_userstyle(GdiCanvas *canvas, uint8_t nseg, SPICE_FIXED28_4* style, int start_is_gap) +{ + uint32_t *local_style; + int i; + + spice_return_val_if_fail(nseg != 0, NULL); + + local_style = spice_new(uint32_t , nseg); + + if (start_is_gap) { + local_style[nseg - 1] = (uint32_t)fix_to_double(*style); + style++; + + for (i = 0; i < nseg - 1; i++, style++) { + local_style[i] = (uint32_t)fix_to_double(*style); + } + } else { + for (i = 0; i < nseg; i++, style++) { + local_style[i] = (uint32_t)fix_to_double(*style); + } + } + + return local_style; +} + +static void gdi_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + HPEN hpen; + HPEN prev_hpen; + LOGBRUSH logbrush; + uint32_t *user_style = NULL; + pixman_image_t *surface = NULL; + + if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + surface = canvas_get_image(&canvas->base, stroke->brush.u.pattern.pat, FALSE); + } + + RecurciveLock lock(*canvas->lock); + set_clip(canvas, clip); + + switch (stroke->fore_mode) { + case SPICE_ROPD_OP_WHITENESS: + SetROP2(canvas->dc, R2_WHITE); //0 + break; + case SPICE_ROPD_OP_BLACKNESS: + SetROP2(canvas->dc, R2_BLACK); //1 + break; + case SPICE_ROPD_OP_INVERS: + SetROP2(canvas->dc, R2_NOT); //Dn + break; + case SPICE_ROPD_OP_PUT: + SetROP2(canvas->dc, R2_COPYPEN); //P + break; + case SPICE_ROPD_OP_OR: + SetROP2(canvas->dc, R2_MERGEPEN); //DPo + break; + case SPICE_ROPD_OP_XOR: + SetROP2(canvas->dc, R2_XORPEN); //DPx + break; + case SPICE_ROPD_OP_AND: + SetROP2(canvas->dc, R2_MASKPEN); //DPa + break; + case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_PUT: //Pn + SetROP2(canvas->dc, R2_NOTCOPYPEN); + break; + case SPICE_ROPD_OP_XOR | SPICE_ROPD_INVERS_RES: + SetROP2(canvas->dc, R2_NOTXORPEN); //DPxn + break; + case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_RES: + SetROP2(canvas->dc, R2_NOTMERGEPEN); //DPon + break; + case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES: + SetROP2(canvas->dc, R2_NOTMASKPEN); //DPan + break; + case SPICE_ROPD_INVERS_DEST | SPICE_ROPD_OP_AND: + SetROP2(canvas->dc, R2_MASKPENNOT); //PDna + break; + case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_AND: + SetROP2(canvas->dc, R2_MASKNOTPEN); //DPna + break; + case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_BRUSH: + SetROP2(canvas->dc, R2_MERGENOTPEN); //DPno + break; + case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_DEST: + SetROP2(canvas->dc, R2_MERGEPENNOT); //PDno + break; + default: + SetROP2(canvas->dc, R2_NOP); //D + } + + + if (stroke->brush.type == SPICE_BRUSH_TYPE_SOLID) { + logbrush.lbStyle = BS_SOLID | DIB_RGB_COLORS; + logbrush.lbHatch = 0; + logbrush.lbColor = get_color_ref(canvas, stroke->brush.u.color); + } else if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { +#if 0 + struct { + BITMAPINFO inf; + RGBQUAD palette[255]; + } bitmap_info; + GdiImage image; +#endif +#if 0 + spice_return_if_fail(surface != NULL) + surface_to_image(surface, &image); + + memset(&bitmap_info, 0, sizeof(bitmap_info)); + bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); + bitmap_info.inf.bmiHeader.biWidth = image.width; + if (image.stride < 0) { + bitmap_info.inf.bmiHeader.biHeight = image.height; + } else { + bitmap_info.inf.bmiHeader.biHeight = -image.height; + } + bitmap_info.inf.bmiHeader.biPlanes = 1; + bitmap_info.inf.bmiHeader.biBitCount = 32; + bitmap_info.inf.bmiHeader.biCompression = BI_RGB; + + if (image.stride < 0) { + logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE, + image.height * -image.stride + sizeof(BITMAPINFO)); + if (!logbrush.lbHatch) { + spice_critical("GlobalAlloc failed"); + return; + } + copy_bitmap(image.pixels - (image.height - 1) * -image.stride, + image.height, -image.stride, + (uint8_t *)logbrush.lbHatch, image.width); + } else { + logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE, + image.height * image.stride + sizeof(BITMAPINFO)); + if (!logbrush.lbHatch) { + spice_critical("GlobalAlloc failed"); + return; + } + copy_bitmap(image.pixels, image.height, image.stride, + (uint8_t *)logbrush.lbHatch, image.width); + } + + memcpy((void *)logbrush.lbHatch, &bitmap_info.inf, sizeof(BITMAPINFO)); + + logbrush.lbStyle = BS_DIBPATTERN | DIB_RGB_COLORS; + logbrush.lbColor = 0; +#endif + pixman_image_unref(surface); + } + + if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { + user_style = gdi_get_userstyle(canvas, stroke->attr.style_nseg, + stroke->attr.style, + !!(stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP)); + hpen = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE, + 1, + &logbrush, stroke->attr.style_nseg, (DWORD *)user_style); + } else { + hpen = ExtCreatePen(PS_COSMETIC, + 1, + &logbrush, 0, NULL); + } + prev_hpen = (HPEN)SelectObject(canvas->dc, hpen); + + set_path(canvas, stroke->path); + + StrokePath(canvas->dc); + + SelectObject(canvas->dc, prev_hpen); + DeleteObject(hpen); + +#if 0 + if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + GlobalFree((HGLOBAL)logbrush.lbHatch); + } +#endif + + free(user_style); +} + +static void gdi_canvas_clear(SpiceCanvas *spice_canvas) +{ +} + +static void gdi_canvas_destroy(SpiceCanvas *spice_canvas) +{ + GdiCanvas *canvas = (GdiCanvas *)spice_canvas; + if (!canvas) { + return; + } + canvas_base_destroy(&canvas->base); + free(canvas); +} + +static int need_init = 1; +static SpiceCanvasOps gdi_canvas_ops; + +SpiceCanvas *gdi_canvas_create(int width, int height, + HDC dc, RecurciveMutex* lock, uint32_t format + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ) +{ + GdiCanvas *canvas; + + if (need_init) { + return NULL; + } + canvas = spice_new0(GdiCanvas, 1); + canvas_base_init(&canvas->base, &gdi_canvas_ops, + width, height, format, + bits_cache, +#ifdef SW_CANVAS_CACHE + palette_cache, +#endif + surfaces, + glz_decoder, + jpeg_decoder, + zlib_decoder); + canvas->dc = dc; + canvas->lock = lock; + return (SpiceCanvas *)canvas; +} + +void gdi_canvas_init(void) //unsafe global function +{ + if (!need_init) { + return; + } + need_init = 0; + + canvas_base_init_ops(&gdi_canvas_ops); + gdi_canvas_ops.draw_fill = gdi_canvas_draw_fill; + gdi_canvas_ops.draw_copy = gdi_canvas_draw_copy; + gdi_canvas_ops.draw_opaque = gdi_canvas_draw_opaque; + gdi_canvas_ops.copy_bits = gdi_canvas_copy_bits; + gdi_canvas_ops.draw_text = gdi_canvas_draw_text; + gdi_canvas_ops.draw_stroke = gdi_canvas_draw_stroke; + gdi_canvas_ops.draw_rop3 = gdi_canvas_draw_rop3; + gdi_canvas_ops.draw_blend = gdi_canvas_draw_blend; + gdi_canvas_ops.draw_blackness = gdi_canvas_draw_blackness; + gdi_canvas_ops.draw_whiteness = gdi_canvas_draw_whiteness; + gdi_canvas_ops.draw_invers = gdi_canvas_draw_invers; + gdi_canvas_ops.draw_transparent = gdi_canvas_draw_transparent; + gdi_canvas_ops.draw_alpha_blend = gdi_canvas_draw_alpha_blend; + gdi_canvas_ops.put_image = gdi_canvas_put_image; + gdi_canvas_ops.clear = gdi_canvas_clear; + gdi_canvas_ops.destroy = gdi_canvas_destroy; +} diff --git a/spice-common/common/gdi_canvas.h b/spice-common/common/gdi_canvas.h new file mode 100644 index 0000000..dc302dc --- /dev/null +++ b/spice-common/common/gdi_canvas.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H__GDI_CANVAS +#define _H__GDI_CANVAS + +#include +#include + +#include "pixman_utils.h" +#include "canvas_base.h" +#include "region.h" + +SPICE_BEGIN_DECLS + +SpiceCanvas *gdi_canvas_create(int width, int height, + HDC dc, class RecurciveMutex *lock, uint32_t format, + SpiceImageCache *bits_cache, + SpicePaletteCache *palette_cache, + SpiceImageSurfaces *surfaces, + SpiceGlzDecoder *glz_decoder, + SpiceJpegDecoder *jpeg_decoder, + SpiceZlibDecoder *zlib_decoder); + +void gdi_canvas_init(void); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/generated_client_demarshallers.c b/spice-common/common/generated_client_demarshallers.c new file mode 100644 index 0000000..62ef234 --- /dev/null +++ b/spice-common/common/generated_client_demarshallers.c @@ -0,0 +1,8206 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#endif + + + +#ifdef WORDS_BIGENDIAN +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) *(int8_t *)(ptr) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) *(uint8_t *)(ptr) = val +#define read_int16(ptr) ((int16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_int16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_uint16(ptr) ((uint16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_uint16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_int32(ptr) ((int32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_int32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_uint32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_int64(ptr) ((int64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_int64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#define read_uint64(ptr) ((uint64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_uint64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#else +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) (*((int8_t *)(ptr))) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) (*((uint8_t *)(ptr))) = val +#define read_int16(ptr) (*((int16_t *)(ptr))) +#define write_int16(ptr, val) (*((int16_t *)(ptr))) = val +#define read_uint16(ptr) (*((uint16_t *)(ptr))) +#define write_uint16(ptr, val) (*((uint16_t *)(ptr))) = val +#define read_int32(ptr) (*((int32_t *)(ptr))) +#define write_int32(ptr, val) (*((int32_t *)(ptr))) = val +#define read_uint32(ptr) (*((uint32_t *)(ptr))) +#define write_uint32(ptr, val) (*((uint32_t *)(ptr))) = val +#define read_int64(ptr) (*((int64_t *)(ptr))) +#define write_int64(ptr, val) (*((int64_t *)(ptr))) = val +#define read_uint64(ptr) (*((uint64_t *)(ptr))) +#define write_uint64(ptr, val) (*((uint64_t *)(ptr))) = val +#endif + +static int8_t SPICE_GNUC_UNUSED consume_int8(uint8_t **ptr) +{ + int8_t val; + val = read_int8(*ptr); + *ptr += 1; + return val; +} + +static uint8_t SPICE_GNUC_UNUSED consume_uint8(uint8_t **ptr) +{ + uint8_t val; + val = read_uint8(*ptr); + *ptr += 1; + return val; +} + +static int16_t SPICE_GNUC_UNUSED consume_int16(uint8_t **ptr) +{ + int16_t val; + val = read_int16(*ptr); + *ptr += 2; + return val; +} + +static uint16_t SPICE_GNUC_UNUSED consume_uint16(uint8_t **ptr) +{ + uint16_t val; + val = read_uint16(*ptr); + *ptr += 2; + return val; +} + +static int32_t SPICE_GNUC_UNUSED consume_int32(uint8_t **ptr) +{ + int32_t val; + val = read_int32(*ptr); + *ptr += 4; + return val; +} + +static uint32_t SPICE_GNUC_UNUSED consume_uint32(uint8_t **ptr) +{ + uint32_t val; + val = read_uint32(*ptr); + *ptr += 4; + return val; +} + +static int64_t SPICE_GNUC_UNUSED consume_int64(uint8_t **ptr) +{ + int64_t val; + val = read_int64(*ptr); + *ptr += 8; + return val; +} + +static uint64_t SPICE_GNUC_UNUSED consume_uint64(uint8_t **ptr) +{ + uint64_t val; + val = read_uint64(*ptr); + *ptr += 8; + return val; +} +static int SPICE_GNUC_UNUSED consume_fd(uint8_t **ptr) +{ + return -1; +} + +typedef struct PointerInfo PointerInfo; +typedef void (*message_destructor_t)(uint8_t *message); +typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor); +typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message); +typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message); + +struct PointerInfo { + uint64_t offset; + parse_func_t parse; + void * *dest; + uint32_t nelements; +}; + +static uint8_t * parse_msg_migrate(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMigrate *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMigrate); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMigrate); + in = start; + + out = (SpiceMsgMigrate *)data; + + out->flags = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static void nofree(SPICE_GNUC_UNUSED uint8_t *data) +{ +} + +static uint8_t * parse_SpiceMsgData(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t data__nw_size; + uint32_t data__nelements; + + { /* data */ + data__nelements = message_end - (start + 0); + + data__nw_size = data__nelements; + } + + nw_size = 0 + data__nw_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = message_start; + *size = message_end - message_start; + *free_message = nofree; + return data; + +} + +static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgSetAck *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgSetAck); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgSetAck); + in = start; + + out = (SpiceMsgSetAck *)data; + + out->generation = consume_uint32(&in); + out->window = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_ping(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPing *out; + + { /* data */ + data__nelements = message_end - (start + 12); + + data__nw_size = data__nelements; + } + + nw_size = 12 + data__nw_size; + mem_size = sizeof(SpiceMsgPing); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPing); + in = start; + + out = (SpiceMsgPing *)data; + + out->id = consume_uint32(&in); + out->timestamp = consume_uint64(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_len = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_wait_for_channels(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t wait_list__nw_size, wait_list__mem_size; + uint32_t wait_list__nelements; + SpiceMsgWaitForChannels *out; + uint32_t i; + + { /* wait_list */ + uint8_t wait_count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + wait_count__value = read_uint8(pos); + wait_list__nelements = wait_count__value; + + wait_list__nw_size = (10) * wait_list__nelements; + wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements; + } + + nw_size = 1 + wait_list__nw_size; + mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgWaitForChannels); + in = start; + + out = (SpiceMsgWaitForChannels *)data; + + out->wait_count = consume_uint8(&in); + for (i = 0; i < wait_list__nelements; i++) { + SpiceWaitForChannel *out2; + out2 = (SpiceWaitForChannel *)end; + end += sizeof(SpiceWaitForChannel); + + out2->channel_type = consume_uint8(&in); + out2->channel_id = consume_uint8(&in); + out2->message_serial = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_disconnecting(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisconnect *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgDisconnect); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisconnect); + in = start; + + out = (SpiceMsgDisconnect *)data; + + out->time_stamp = consume_uint64(&in); + out->reason = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_notify(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t message__nw_size, message__mem_size; + uint32_t message__nelements; + SpiceMsgNotify *out; + + { /* message */ + uint32_t message_len__value; + pos = start + 20; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + message_len__value = read_uint32(pos); + message__nelements = message_len__value; + + message__nw_size = message__nelements; + message__mem_size = sizeof(uint8_t) * message__nelements; + } + + nw_size = 24 + message__nw_size; + mem_size = sizeof(SpiceMsgNotify) + message__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgNotify); + in = start; + + out = (SpiceMsgNotify *)data; + + out->time_stamp = consume_uint64(&in); + out->severity = consume_uint32(&in); + out->visibilty = consume_uint32(&in); + out->what = consume_uint32(&in); + out->message_len = consume_uint32(&in); + memcpy(out->message, in, message__nelements); + in += message__nelements; + end += message__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SpiceMsgEmpty(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + + nw_size = 0; + mem_size = sizeof(SpiceMsgEmpty); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgEmpty); + in = start; + + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_array_uint8(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + + end = struct_data; + memcpy(end, in, this_ptr_info->nelements); + in += this_ptr_info->nelements; + end += this_ptr_info->nelements; + return end; +} + +static uint8_t * parse_msg_main_migrate_begin(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t dst_info__extra_size; + SpiceMsgMainMigrationBegin *out; + uint32_t i; + + { /* dst_info */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t dst_info_host_data__extra_size; + uint32_t dst_info_host_data__array__nelements; + size_t dst_info_cert_subject_data__extra_size; + uint32_t dst_info_cert_subject_data__array__nelements; + { /* host_data */ + uint32_t host_data__value; + uint32_t dst_info_host_data__array__nw_size; + uint32_t dst_info_host_data__array__mem_size; + uint32_t host_size__value; + pos = (start2 + 8); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(host_data__value == 0)) { + goto error; + } + if (SPICE_UNLIKELY(message_start + host_data__value >= message_end)) { + goto error; + } + pos = start2 + 4; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_size__value = read_uint32(pos); + dst_info_host_data__array__nelements = host_size__value; + + dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements; + dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements; + if (SPICE_UNLIKELY(message_start + host_data__value + dst_info_host_data__array__nw_size > message_end)) { + goto error; + } + dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3; + } + + { /* cert_subject_data */ + uint32_t cert_subject_data__value; + uint32_t dst_info_cert_subject_data__array__nw_size; + uint32_t dst_info_cert_subject_data__array__mem_size; + uint32_t cert_subject_size__value; + pos = (start2 + 16); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + cert_subject_data__value >= message_end)) { + goto error; + } + pos = start2 + 12; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_size__value = read_uint32(pos); + dst_info_cert_subject_data__array__nelements = cert_subject_size__value; + + dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements; + dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements; + if (SPICE_UNLIKELY(message_start + cert_subject_data__value + dst_info_cert_subject_data__array__nw_size > message_end)) { + goto error; + } + dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3; + } + + dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size; + } + + nw_size = 20; + mem_size = sizeof(SpiceMsgMainMigrationBegin) + dst_info__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMigrationBegin); + in = start; + + out = (SpiceMsgMainMigrationBegin *)data; + + /* dst_info */ { + uint32_t host_data__array__nelements; + uint32_t cert_subject_data__array__nelements; + out->dst_info.port = consume_uint16(&in); + out->dst_info.sport = consume_uint16(&in); + out->dst_info.host_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data; + host_data__array__nelements = out->dst_info.host_size; + ptr_info[n_ptr].nelements = host_data__array__nelements; + n_ptr++; + out->dst_info.cert_subject_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data; + cert_subject_data__array__nelements = out->dst_info.cert_subject_size; + ptr_info[n_ptr].nelements = cert_subject_data__array__nelements; + n_ptr++; + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainInit *out; + + nw_size = 32; + mem_size = sizeof(SpiceMsgMainInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainInit); + in = start; + + out = (SpiceMsgMainInit *)data; + + out->session_id = consume_uint32(&in); + out->display_channels_hint = consume_uint32(&in); + out->supported_mouse_modes = consume_uint32(&in); + out->current_mouse_mode = consume_uint32(&in); + out->agent_connected = consume_uint32(&in); + out->agent_tokens = consume_uint32(&in); + out->multi_media_time = consume_uint32(&in); + out->ram_hint = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_channels_list(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t channels__nw_size, channels__mem_size; + uint32_t channels__nelements; + SpiceMsgChannels *out; + uint32_t i; + + { /* channels */ + uint32_t num_of_channels__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_of_channels__value = read_uint32(pos); + channels__nelements = num_of_channels__value; + + channels__nw_size = (2) * channels__nelements; + channels__mem_size = sizeof(SpiceChannelId) * channels__nelements; + } + + nw_size = 4 + channels__nw_size; + mem_size = sizeof(SpiceMsgChannels) + channels__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgChannels); + in = start; + + out = (SpiceMsgChannels *)data; + + out->num_of_channels = consume_uint32(&in); + for (i = 0; i < channels__nelements; i++) { + SpiceChannelId *out2; + out2 = (SpiceChannelId *)end; + end += sizeof(SpiceChannelId); + + out2->type = consume_uint8(&in); + out2->id = consume_uint8(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_mouse_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainMouseMode *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainMouseMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMouseMode); + in = start; + + out = (SpiceMsgMainMouseMode *)data; + + out->supported_modes = consume_uint16(&in); + out->current_mode = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_multi_media_time(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainMultiMediaTime *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainMultiMediaTime); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMultiMediaTime); + in = start; + + out = (SpiceMsgMainMultiMediaTime *)data; + + out->time = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_agent_disconnected(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainAgentDisconnect *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainAgentDisconnect); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainAgentDisconnect); + in = start; + + out = (SpiceMsgMainAgentDisconnect *)data; + + out->error_code = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_agent_token(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainAgentTokens *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainAgentTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainAgentTokens); + in = start; + + out = (SpiceMsgMainAgentTokens *)data; + + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_migrate_switch_host(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t host_data__extra_size; + uint32_t host_data__array__nelements; + size_t cert_subject_data__extra_size; + uint32_t cert_subject_data__array__nelements; + SpiceMsgMainMigrationSwitchHost *out; + uint32_t i; + + { /* host_data */ + uint32_t host_data__value; + uint32_t host_data__array__nw_size; + uint32_t host_data__array__mem_size; + uint32_t host_size__value; + pos = (start + 8); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + host_data__value >= message_end)) { + goto error; + } + pos = start + 4; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_size__value = read_uint32(pos); + host_data__array__nelements = host_size__value; + + host_data__array__nw_size = host_data__array__nelements; + host_data__array__mem_size = sizeof(uint8_t) * host_data__array__nelements; + if (SPICE_UNLIKELY(message_start + host_data__value + host_data__array__nw_size > message_end)) { + goto error; + } + host_data__extra_size = host_data__array__mem_size + /* for alignment */ 3; + } + + { /* cert_subject_data */ + uint32_t cert_subject_data__value; + uint32_t cert_subject_data__array__nw_size; + uint32_t cert_subject_data__array__mem_size; + uint32_t cert_subject_size__value; + pos = (start + 16); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + cert_subject_data__value >= message_end)) { + goto error; + } + pos = start + 12; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_size__value = read_uint32(pos); + cert_subject_data__array__nelements = cert_subject_size__value; + + cert_subject_data__array__nw_size = cert_subject_data__array__nelements; + cert_subject_data__array__mem_size = sizeof(uint8_t) * cert_subject_data__array__nelements; + if (SPICE_UNLIKELY(message_start + cert_subject_data__value + cert_subject_data__array__nw_size > message_end)) { + goto error; + } + cert_subject_data__extra_size = cert_subject_data__array__mem_size + /* for alignment */ 3; + } + + nw_size = 20; + mem_size = sizeof(SpiceMsgMainMigrationSwitchHost) + host_data__extra_size + cert_subject_data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMigrationSwitchHost); + in = start; + + out = (SpiceMsgMainMigrationSwitchHost *)data; + + out->port = consume_uint16(&in); + out->sport = consume_uint16(&in); + out->host_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->host_data; + ptr_info[n_ptr].nelements = host_data__array__nelements; + n_ptr++; + out->cert_subject_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->cert_subject_data; + ptr_info[n_ptr].nelements = cert_subject_data__array__nelements; + n_ptr++; + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_name(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t name__nw_size, name__mem_size; + uint32_t name__nelements; + SpiceMsgMainName *out; + + { /* name */ + uint32_t name_len__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + name_len__value = read_uint32(pos); + name__nelements = name_len__value; + + name__nw_size = name__nelements; + name__mem_size = sizeof(uint8_t) * name__nelements; + } + + nw_size = 4 + name__nw_size; + mem_size = sizeof(SpiceMsgMainName) + name__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainName); + in = start; + + out = (SpiceMsgMainName *)data; + + out->name_len = consume_uint32(&in); + memcpy(out->name, in, name__nelements); + in += name__nelements; + end += name__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_uuid(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainUuid *out; + uint32_t uuid__nelements; + + nw_size = 16; + mem_size = sizeof(SpiceMsgMainUuid); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainUuid); + in = start; + + out = (SpiceMsgMainUuid *)data; + + uuid__nelements = 16; + memcpy(out->uuid, in, uuid__nelements); + in += uuid__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_agent_connected_tokens(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainAgentConnectedTokens *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainAgentConnectedTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainAgentConnectedTokens); + in = start; + + out = (SpiceMsgMainAgentConnectedTokens *)data; + + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_migrate_begin_seamless(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t dst_info__extra_size; + SpiceMsgMainMigrateBeginSeamless *out; + uint32_t i; + + { /* dst_info */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t dst_info_host_data__extra_size; + uint32_t dst_info_host_data__array__nelements; + size_t dst_info_cert_subject_data__extra_size; + uint32_t dst_info_cert_subject_data__array__nelements; + { /* host_data */ + uint32_t host_data__value; + uint32_t dst_info_host_data__array__nw_size; + uint32_t dst_info_host_data__array__mem_size; + uint32_t host_size__value; + pos = (start2 + 8); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(host_data__value == 0)) { + goto error; + } + if (SPICE_UNLIKELY(message_start + host_data__value >= message_end)) { + goto error; + } + pos = start2 + 4; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_size__value = read_uint32(pos); + dst_info_host_data__array__nelements = host_size__value; + + dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements; + dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements; + if (SPICE_UNLIKELY(message_start + host_data__value + dst_info_host_data__array__nw_size > message_end)) { + goto error; + } + dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3; + } + + { /* cert_subject_data */ + uint32_t cert_subject_data__value; + uint32_t dst_info_cert_subject_data__array__nw_size; + uint32_t dst_info_cert_subject_data__array__mem_size; + uint32_t cert_subject_size__value; + pos = (start2 + 16); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_data__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + cert_subject_data__value >= message_end)) { + goto error; + } + pos = start2 + 12; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_size__value = read_uint32(pos); + dst_info_cert_subject_data__array__nelements = cert_subject_size__value; + + dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements; + dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements; + if (SPICE_UNLIKELY(message_start + cert_subject_data__value + dst_info_cert_subject_data__array__nw_size > message_end)) { + goto error; + } + dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3; + } + + dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size; + } + + nw_size = 24; + mem_size = sizeof(SpiceMsgMainMigrateBeginSeamless) + dst_info__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMigrateBeginSeamless); + in = start; + + out = (SpiceMsgMainMigrateBeginSeamless *)data; + + /* dst_info */ { + uint32_t host_data__array__nelements; + uint32_t cert_subject_data__array__nelements; + out->dst_info.port = consume_uint16(&in); + out->dst_info.sport = consume_uint16(&in); + out->dst_info.host_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data; + host_data__array__nelements = out->dst_info.host_size; + ptr_info[n_ptr].nelements = host_data__array__nelements; + n_ptr++; + out->dst_info.cert_subject_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data; + cert_subject_data__array__nelements = out->dst_info.cert_subject_size; + ptr_info[n_ptr].nelements = cert_subject_data__array__nelements; + n_ptr++; + } + out->src_mig_version = consume_uint32(&in); + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_MainChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[19] = { + parse_SpiceMsgEmpty, + parse_msg_main_migrate_begin, + parse_SpiceMsgEmpty, + parse_msg_main_init, + parse_msg_main_channels_list, + parse_msg_main_mouse_mode, + parse_msg_main_multi_media_time, + parse_SpiceMsgEmpty, + parse_msg_main_agent_disconnected, + parse_SpiceMsgData, + parse_msg_main_agent_token, + parse_msg_main_migrate_switch_host, + parse_SpiceMsgEmpty, + parse_msg_main_name, + parse_msg_main_uuid, + parse_msg_main_agent_connected_tokens, + parse_msg_main_migrate_begin_seamless, + parse_SpiceMsgEmpty, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 119) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_display_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayMode *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgDisplayMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayMode); + in = start; + + out = (SpiceMsgDisplayMode *)data; + + out->x_res = consume_uint32(&in); + out->y_res = consume_uint32(&in); + out->bits = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_struct_SpiceClipRects(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpiceClipRects *out; + uint32_t rects__nelements; + uint32_t i; + + end = struct_data + sizeof(SpiceClipRects); + out = (SpiceClipRects *)struct_data; + + out->num_rects = consume_uint32(&in); + rects__nelements = out->num_rects; + for (i = 0; i < rects__nelements; i++) { + SpiceRect *out2; + out2 = (SpiceRect *)end; + end += sizeof(SpiceRect); + + out2->top = consume_int32(&in); + out2->left = consume_int32(&in); + out2->bottom = consume_int32(&in); + out2->right = consume_int32(&in); + } + return end; +} + +static uint8_t * parse_msg_display_copy_bits(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + SpiceMsgDisplayCopyBits *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + nw_size = 8 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayCopyBits) + base__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayCopyBits); + in = start; + + out = (SpiceMsgDisplayCopyBits *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* src_pos */ { + out->src_pos.x = consume_int32(&in); + out->src_pos.y = consume_int32(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_list(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t resources__nw_size, resources__mem_size; + uint32_t resources__nelements; + SpiceResourceList *out; + uint32_t i; + + { /* resources */ + uint16_t count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + count__value = read_uint16(pos); + resources__nelements = count__value; + + resources__nw_size = (9) * resources__nelements; + resources__mem_size = sizeof(SpiceResourceID) * resources__nelements; + } + + nw_size = 2 + resources__nw_size; + mem_size = sizeof(SpiceResourceList) + resources__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceResourceList); + in = start; + + out = (SpiceResourceList *)data; + + out->count = consume_uint16(&in); + for (i = 0; i < resources__nelements; i++) { + SpiceResourceID *out2; + out2 = (SpiceResourceID *)end; + end += sizeof(SpiceResourceID); + + out2->type = consume_uint8(&in); + out2->id = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_all_pixmaps(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t wait_list__nw_size, wait_list__mem_size; + uint32_t wait_list__nelements; + SpiceMsgWaitForChannels *out; + uint32_t i; + + { /* wait_list */ + uint8_t wait_count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + wait_count__value = read_uint8(pos); + wait_list__nelements = wait_count__value; + + wait_list__nw_size = (10) * wait_list__nelements; + wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements; + } + + nw_size = 1 + wait_list__nw_size; + mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgWaitForChannels); + in = start; + + out = (SpiceMsgWaitForChannels *)data; + + out->wait_count = consume_uint8(&in); + for (i = 0; i < wait_list__nelements; i++) { + SpiceWaitForChannel *out2; + out2 = (SpiceWaitForChannel *)end; + end += sizeof(SpiceWaitForChannel); + + out2->channel_type = consume_uint8(&in); + out2->channel_id = consume_uint8(&in); + out2->message_serial = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_palette(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayInvalOne *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgDisplayInvalOne); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayInvalOne); + in = start; + + out = (SpiceMsgDisplayInvalOne *)data; + + out->id = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_create(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t clip__nw_size, clip__extra_size; + uint32_t rects__saved_size = 0; + SpiceMsgDisplayStreamCreate *out; + uint32_t i; + + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 50); + size_t clip_u__nw_size, clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t clip_u__mem_size; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1); + size_t clip_u_rects__nw_size, clip_u_rects__mem_size; + uint32_t clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + clip_u_rects__nelements = num_rects__value; + + clip_u_rects__nw_size = (16) * clip_u_rects__nelements; + clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements; + } + + clip_u__nw_size = 4 + clip_u_rects__nw_size; + clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size; + rects__saved_size = clip_u__nw_size; + clip_u__extra_size = clip_u__mem_size; + } else { + clip_u__nw_size = 0; + clip_u__extra_size = 0; + } + + } + + clip__nw_size = 1 + clip_u__nw_size; + clip__extra_size = clip_u__extra_size; + } + + nw_size = 50 + clip__nw_size; + mem_size = sizeof(SpiceMsgDisplayStreamCreate) + clip__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamCreate); + in = start; + + out = (SpiceMsgDisplayStreamCreate *)data; + + out->surface_id = consume_uint32(&in); + out->id = consume_uint32(&in); + out->flags = consume_uint8(&in); + out->codec_type = consume_uint8(&in); + out->stamp = consume_uint64(&in); + out->stream_width = consume_uint32(&in); + out->stream_height = consume_uint32(&in); + out->src_width = consume_uint32(&in); + out->src_height = consume_uint32(&in); + /* dest */ { + out->dest.top = consume_int32(&in); + out->dest.left = consume_int32(&in); + out->dest.bottom = consume_int32(&in); + out->dest.right = consume_int32(&in); + } + /* clip */ { + out->clip.type = consume_uint8(&in); + if (out->clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgDisplayStreamData *out; + + { /* data */ + uint32_t data_size__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + data__nelements = data_size__value; + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 12 + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayStreamData) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamData); + in = start; + + out = (SpiceMsgDisplayStreamData *)data; + + /* base */ { + out->base.id = consume_uint32(&in); + out->base.multi_media_time = consume_uint32(&in); + } + out->data_size = consume_uint32(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_clip(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t clip__nw_size, clip__extra_size; + uint32_t rects__saved_size = 0; + SpiceMsgDisplayStreamClip *out; + uint32_t i; + + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 4); + size_t clip_u__nw_size, clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t clip_u__mem_size; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1); + size_t clip_u_rects__nw_size, clip_u_rects__mem_size; + uint32_t clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + clip_u_rects__nelements = num_rects__value; + + clip_u_rects__nw_size = (16) * clip_u_rects__nelements; + clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements; + } + + clip_u__nw_size = 4 + clip_u_rects__nw_size; + clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size; + rects__saved_size = clip_u__nw_size; + clip_u__extra_size = clip_u__mem_size; + } else { + clip_u__nw_size = 0; + clip_u__extra_size = 0; + } + + } + + clip__nw_size = 1 + clip_u__nw_size; + clip__extra_size = clip_u__extra_size; + } + + nw_size = 4 + clip__nw_size; + mem_size = sizeof(SpiceMsgDisplayStreamClip) + clip__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamClip); + in = start; + + out = (SpiceMsgDisplayStreamClip *)data; + + out->id = consume_uint32(&in); + /* clip */ { + out->clip.type = consume_uint8(&in); + if (out->clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_destroy(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayStreamDestroy *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgDisplayStreamDestroy); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamDestroy); + in = start; + + out = (SpiceMsgDisplayStreamDestroy *)data; + + out->id = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpicePalette(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t ents__nw_size, ents__mem_size; + uint32_t ents__nelements; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* ents */ + uint16_t num_ents__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + num_ents__value = read_uint16(pos); + ents__nelements = num_ents__value; + + ents__nw_size = (4) * ents__nelements; + ents__mem_size = sizeof(uint32_t) * ents__nelements; + } + + nw_size = 10 + ents__nw_size; + mem_size = sizeof(SpicePalette) + ents__mem_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static intptr_t validate_SpiceImage(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + SPICE_GNUC_UNUSED intptr_t ptr_size; + size_t u__nw_size, u__extra_size; + uint8_t descriptor_type__value; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* u */ + pos = start + 8; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + descriptor_type__value = read_uint8(pos); + if (descriptor_type__value == SPICE_IMAGE_TYPE_BITMAP) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_pal__nw_size, u_pal__extra_size; + uint8_t flags__value; + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* pal */ + pos = start2 + 1; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + u_pal__nw_size = 8; + u_pal__extra_size = 0; + } else if (1) { + uint32_t u_pal_palette__value; + u_pal__nw_size = 4; + pos = (start2 + 14); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + u_pal_palette__value = read_uint32(pos); + ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + u_pal__extra_size = ptr_size + /* for alignment */ 3; + } else { + u_pal__nw_size = 0; + u_pal__extra_size = 0; + } + + } + + { /* data */ + uint32_t stride__value; + uint32_t y__value; + pos = start2 + 10; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + stride__value = read_uint32(pos); + pos = start2 + 6; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + y__value = read_uint32(pos); + u_data__nelements = stride__value * y__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 14 + u_pal__nw_size + u_data__nw_size; + u__extra_size = u_pal__extra_size + u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_QUIC) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_RGB || descriptor_type__value == SPICE_IMAGE_TYPE_GLZ_RGB) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ4) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_PLT) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_pal__nw_size, u_pal__extra_size; + uint8_t flags__value; + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* pal */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + u_pal__nw_size = 8; + u_pal__extra_size = 0; + } else if (1) { + uint32_t u_pal_palette__value; + u_pal__nw_size = 4; + pos = (start2 + 5); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + u_pal_palette__value = read_uint32(pos); + if (SPICE_UNLIKELY(u_pal_palette__value == 0)) { + goto error; + } + ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + u_pal__extra_size = ptr_size + /* for alignment */ 3; + } else { + u_pal__nw_size = 0; + u_pal__extra_size = 0; + } + + } + + { /* data */ + uint32_t data_size__value; + pos = start2 + 1; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 5 + u_pal__nw_size + u_data__nw_size; + u__extra_size = u_pal__extra_size + u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 4; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 8 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG_ALPHA) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 5; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 9 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_SURFACE) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + u__nw_size = 4; + u__extra_size = 0; + } else { + u__nw_size = 0; + u__extra_size = 0; + } + + } + + nw_size = 18 + u__nw_size; + mem_size = sizeof(SpiceImage) + u__extra_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpicePalette(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpicePalette *out; + uint32_t ents__nelements; + uint32_t i; + + end = struct_data + sizeof(SpicePalette); + out = (SpicePalette *)struct_data; + + out->unique = consume_uint64(&in); + out->num_ents = consume_uint16(&in); + ents__nelements = out->num_ents; + for (i = 0; i < ents__nelements; i++) { + out->ents[i] = consume_uint32(&in); + end += sizeof(uint32_t); + } + return end; +} + +static uint8_t * parse_struct_SpiceImage(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + SpiceImage *out; + uint32_t i; + + end = struct_data + sizeof(SpiceImage); + out = (SpiceImage *)struct_data; + + /* descriptor */ { + out->descriptor.id = consume_uint64(&in); + out->descriptor.type = consume_uint8(&in); + out->descriptor.flags = consume_uint8(&in); + out->descriptor.width = consume_uint32(&in); + out->descriptor.height = consume_uint32(&in); + } + if (out->descriptor.type == SPICE_IMAGE_TYPE_BITMAP) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.bitmap.format = consume_uint8(&in); + out->u.bitmap.flags = consume_uint8(&in); + out->u.bitmap.x = consume_uint32(&in); + out->u.bitmap.y = consume_uint32(&in); + out->u.bitmap.stride = consume_uint32(&in); + if ((out->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + out->u.bitmap.palette_id = consume_uint64(&in); + } else if (1) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePalette; + ptr_info[n_ptr].dest = (void **)&out->u.bitmap.palette; + n_ptr++; + } + data__nelements = out->u.bitmap.stride * out->u.bitmap.y; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.bitmap.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_QUIC) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.quic.data_size = consume_uint32(&in); + data__nelements = out->u.quic.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.quic.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB || out->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.lz_rgb.data_size = consume_uint32(&in); + data__nelements = out->u.lz_rgb.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.lz_rgb.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.jpeg.data_size = consume_uint32(&in); + data__nelements = out->u.jpeg.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.jpeg.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ4) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.lz4.data_size = consume_uint32(&in); + data__nelements = out->u.lz4.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.lz4.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.lz_plt.flags = consume_uint8(&in); + out->u.lz_plt.data_size = consume_uint32(&in); + if ((out->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + out->u.lz_plt.palette_id = consume_uint64(&in); + } else if (1) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePalette; + ptr_info[n_ptr].dest = (void **)&out->u.lz_plt.palette; + n_ptr++; + } + data__nelements = out->u.lz_plt.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.lz_plt.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.zlib_glz.glz_data_size = consume_uint32(&in); + out->u.zlib_glz.data_size = consume_uint32(&in); + data__nelements = out->u.zlib_glz.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.zlib_glz.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG_ALPHA) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.jpeg_alpha.flags = consume_uint8(&in); + out->u.jpeg_alpha.jpeg_size = consume_uint32(&in); + out->u.jpeg_alpha.data_size = consume_uint32(&in); + data__nelements = out->u.jpeg_alpha.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.jpeg_alpha.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + out->u.surface.surface_id = consume_uint32(&in); + } + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + return end; + + error: + return NULL; +} + +static uint8_t * parse_msg_display_draw_fill(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawFill *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_brush__nw_size, data_brush__extra_size; + size_t data_mask__extra_size; + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_brush_u__nw_size, data_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__nw_size = 4; + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__nw_size = 12; + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__nw_size = 0; + data_brush_u__extra_size = 0; + } + + } + + data_brush__nw_size = 1 + data_brush_u__nw_size; + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2 + data_brush__nw_size); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__nw_size = 15 + data_brush__nw_size; + data__extra_size = data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawFill) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawFill); + in = start; + + out = (SpiceMsgDisplayDrawFill *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + /* brush */ { + out->data.brush.type = consume_uint8(&in); + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + out->data.rop_descriptor = consume_uint16(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_opaque(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawOpaque *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + size_t data_brush__nw_size, data_brush__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t data_brush_u__nw_size, data_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__nw_size = 4; + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__nw_size = 12; + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__nw_size = 0; + data_brush_u__extra_size = 0; + } + + } + + data_brush__nw_size = 1 + data_brush_u__nw_size; + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23 + data_brush__nw_size); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__nw_size = 36 + data_brush__nw_size; + data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawOpaque) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawOpaque); + in = start; + + out = (SpiceMsgDisplayDrawOpaque *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + /* brush */ { + out->data.brush.type = consume_uint8(&in); + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_copy(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawCopy *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size; + } + + nw_size = 36 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawCopy); + in = start; + + out = (SpiceMsgDisplayDrawCopy *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_blend(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawBlend *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size; + } + + nw_size = 36 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawBlend) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawBlend); + in = start; + + out = (SpiceMsgDisplayDrawBlend *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_blackness(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawBlackness *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 13 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawBlackness) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawBlackness); + in = start; + + out = (SpiceMsgDisplayDrawBlackness *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_whiteness(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawWhiteness *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 13 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawWhiteness) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawWhiteness); + in = start; + + out = (SpiceMsgDisplayDrawWhiteness *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_invers(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawInvers *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 13 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawInvers) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawInvers); + in = start; + + out = (SpiceMsgDisplayDrawInvers *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_rop3(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawRop3 *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + size_t data_brush__nw_size, data_brush__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t data_brush_u__nw_size, data_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__nw_size = 4; + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__nw_size = 12; + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__nw_size = 0; + data_brush_u__extra_size = 0; + } + + } + + data_brush__nw_size = 1 + data_brush_u__nw_size; + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 22 + data_brush__nw_size); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint32_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__nw_size = 35 + data_brush__nw_size; + data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawRop3) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawRop3); + in = start; + + out = (SpiceMsgDisplayDrawRop3 *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + /* brush */ { + out->data.brush.type = consume_uint8(&in); + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + out->data.rop3 = consume_uint8(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpicePath(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t segments__nw_size, segments__mem_size; + uint32_t segments__nelements; + uint32_t i; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* segments */ + uint32_t num_segments__value; + uint8_t *start2 = (start + 4); + uint32_t segments__element__nw_size; + uint32_t segments__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_segments__value = read_uint32(pos); + segments__nelements = num_segments__value; + + segments__nw_size = 0; + segments__mem_size = 0; + for (i = 0; i < segments__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t segments__element_points__nw_size, segments__element_points__mem_size; + uint32_t segments__element_points__nelements; + { /* points */ + uint32_t count__value; + pos = start3 + 1; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + count__value = read_uint32(pos); + segments__element_points__nelements = count__value; + + segments__element_points__nw_size = (8) * segments__element_points__nelements; + segments__element_points__mem_size = sizeof(SpicePointFix) * segments__element_points__nelements; + } + + segments__element__nw_size = 5 + segments__element_points__nw_size; + segments__element__mem_size = sizeof(SpicePathSeg) + segments__element_points__mem_size; + segments__nw_size += segments__element__nw_size; + segments__mem_size += sizeof(void *) + SPICE_ALIGN(segments__element__mem_size, 4); + start2 += segments__element__nw_size; + } + } + + nw_size = 4 + segments__nw_size; + mem_size = sizeof(SpicePath) + segments__mem_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpicePath(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpicePath *out; + uint32_t segments__nelements; + uint32_t i; + void * *ptr_array; + int ptr_array_index; + uint32_t j; + + end = struct_data + sizeof(SpicePath); + out = (SpicePath *)struct_data; + + out->num_segments = consume_uint32(&in); + segments__nelements = out->num_segments; + ptr_array_index = 0; + ptr_array = (void **)out->segments; + end += sizeof(void *) * segments__nelements; + for (i = 0; i < segments__nelements; i++) { + SpicePathSeg *out2; + uint32_t points__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpicePathSeg *)end; + end += sizeof(SpicePathSeg); + + out2->flags = consume_uint8(&in); + out2->count = consume_uint32(&in); + points__nelements = out2->count; + for (j = 0; j < points__nelements; j++) { + SpicePointFix *out3; + out3 = (SpicePointFix *)end; + end += sizeof(SpicePointFix); + + out3->x = consume_int32(&in); + out3->y = consume_int32(&in); + } + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + return end; +} + +static uint8_t * parse_array_int32(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + uint32_t i; + + end = struct_data; + for (i = 0; i < this_ptr_info->nelements; i++) { + *(SPICE_FIXED28_4 *)end = consume_int32(&in); + end += sizeof(SPICE_FIXED28_4); + } + return end; +} + +static uint8_t * parse_msg_display_draw_stroke(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawStroke *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_path__extra_size; + size_t data_attr__nw_size, data_attr__extra_size; + size_t data_brush__nw_size, data_brush__extra_size; + { /* path */ + uint32_t path__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + path__value = read_uint32(pos); + if (SPICE_UNLIKELY(path__value == 0)) { + goto error; + } + ptr_size = validate_SpicePath(message_start, message_end, path__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_path__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* attr */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4); + size_t data_attr_u1__nw_size; + uint8_t flags__value; + size_t data_attr_u2__nw_size, data_attr_u2__extra_size; + { /* u1 */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_LINE_FLAGS_STYLED)) { + data_attr_u1__nw_size = 1; + } else { + data_attr_u1__nw_size = 0; + } + + } + + { /* u2 */ + uint32_t data_attr_u2__array__nelements; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_LINE_FLAGS_STYLED)) { + uint32_t data_attr_u2_style__value; + uint32_t data_attr_u2__array__nw_size; + uint32_t data_attr_u2__array__mem_size; + uint8_t style_nseg__value; + data_attr_u2__nw_size = 4; + pos = (start3 + 1 + data_attr_u1__nw_size); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_attr_u2_style__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + data_attr_u2_style__value >= message_end)) { + goto error; + } + pos = start3 + 1; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + style_nseg__value = read_uint8(pos); + data_attr_u2__array__nelements = style_nseg__value; + + data_attr_u2__array__nw_size = (4) * data_attr_u2__array__nelements; + data_attr_u2__array__mem_size = sizeof(SPICE_FIXED28_4) * data_attr_u2__array__nelements; + if (SPICE_UNLIKELY(message_start + data_attr_u2_style__value + data_attr_u2__array__nw_size > message_end)) { + goto error; + } + data_attr_u2__extra_size = data_attr_u2__array__mem_size + /* for alignment */ 3; + } else { + data_attr_u2__nw_size = 0; + data_attr_u2__extra_size = 0; + } + + } + + data_attr__nw_size = 1 + data_attr_u1__nw_size + data_attr_u2__nw_size; + data_attr__extra_size = data_attr_u2__extra_size; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4 + data_attr__nw_size); + size_t data_brush_u__nw_size, data_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__nw_size = 4; + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__nw_size = 12; + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__nw_size = 0; + data_brush_u__extra_size = 0; + } + + } + + data_brush__nw_size = 1 + data_brush_u__nw_size; + data_brush__extra_size = data_brush_u__extra_size; + } + + data__nw_size = 8 + data_attr__nw_size + data_brush__nw_size; + data__extra_size = data_path__extra_size + data_attr__extra_size + data_brush__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawStroke) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawStroke); + in = start; + + out = (SpiceMsgDisplayDrawStroke *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePath; + ptr_info[n_ptr].dest = (void **)&out->data.path; + n_ptr++; + /* attr */ { + out->data.attr.flags = consume_uint8(&in); + if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) { + out->data.attr.style_nseg = consume_uint8(&in); + } + if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) { + uint32_t style__array__nelements; + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_int32; + ptr_info[n_ptr].dest = (void **)&out->data.attr.style; + style__array__nelements = out->data.attr.style_nseg; + ptr_info[n_ptr].nelements = style__array__nelements; + n_ptr++; + } + } + /* brush */ { + out->data.brush.type = consume_uint8(&in); + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + out->data.fore_mode = consume_uint16(&in); + out->data.back_mode = consume_uint16(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpiceString(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t u__nw_size, u__extra_size; + uint8_t flags__value; + uint32_t i; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* u */ + uint32_t u__mem_size; + uint32_t u__nelements; + pos = start + 2; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_STRING_FLAGS_RASTER_A1)) { + uint16_t length__value; + uint8_t *start2 = (start + 3); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = ((width__value + 7) / 8 ) * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A4)) { + uint16_t length__value; + uint8_t *start2 = (start + 3); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = ((4 * width__value + 7) / 8 ) * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A8)) { + uint16_t length__value; + uint8_t *start2 = (start + 3); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = width__value * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else { + u__nw_size = 0; + u__extra_size = 0; + } + + } + + nw_size = 3 + u__nw_size; + mem_size = sizeof(SpiceString) + u__extra_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpiceString(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpiceString *out; + uint32_t i; + + end = struct_data + sizeof(SpiceString); + out = (SpiceString *)struct_data; + + out->length = consume_uint16(&in); + out->flags = consume_uint8(&in); + if ((out->flags & SPICE_STRING_FLAGS_RASTER_A1)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = ((out2->width + 7) / 8 ) * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A4)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = ((4 * out2->width + 7) / 8 ) * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A8)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = out2->width * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } + return end; +} + +static uint8_t * parse_msg_display_draw_text(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawText *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_str__extra_size; + size_t data_fore_brush__nw_size, data_fore_brush__extra_size; + size_t data_back_brush__nw_size, data_back_brush__extra_size; + { /* str */ + uint32_t str__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + str__value = read_uint32(pos); + if (SPICE_UNLIKELY(str__value == 0)) { + goto error; + } + ptr_size = validate_SpiceString(message_start, message_end, str__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_str__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* fore_brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t data_fore_brush_u__nw_size, data_fore_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_fore_brush_u__nw_size = 4; + data_fore_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_fore_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_fore_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_fore_brush_u__nw_size = 12; + data_fore_brush_u__extra_size = data_fore_brush_u_pat__extra_size; + } else { + data_fore_brush_u__nw_size = 0; + data_fore_brush_u__extra_size = 0; + } + + } + + data_fore_brush__nw_size = 1 + data_fore_brush_u__nw_size; + data_fore_brush__extra_size = data_fore_brush_u__extra_size; + } + + { /* back_brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20 + data_fore_brush__nw_size); + size_t data_back_brush_u__nw_size, data_back_brush_u__extra_size; + uint8_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_back_brush_u__nw_size = 4; + data_back_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t data_back_brush_u_pat__extra_size; + { /* pat */ + uint32_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pat__value = read_uint32(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_back_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_back_brush_u__nw_size = 12; + data_back_brush_u__extra_size = data_back_brush_u_pat__extra_size; + } else { + data_back_brush_u__nw_size = 0; + data_back_brush_u__extra_size = 0; + } + + } + + data_back_brush__nw_size = 1 + data_back_brush_u__nw_size; + data_back_brush__extra_size = data_back_brush_u__extra_size; + } + + data__nw_size = 24 + data_fore_brush__nw_size + data_back_brush__nw_size; + data__extra_size = data_str__extra_size + data_fore_brush__extra_size + data_back_brush__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawText) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawText); + in = start; + + out = (SpiceMsgDisplayDrawText *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceString; + ptr_info[n_ptr].dest = (void **)&out->data.str; + n_ptr++; + /* back_area */ { + out->data.back_area.top = consume_int32(&in); + out->data.back_area.left = consume_int32(&in); + out->data.back_area.bottom = consume_int32(&in); + out->data.back_area.right = consume_int32(&in); + } + /* fore_brush */ { + out->data.fore_brush.type = consume_uint8(&in); + if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.fore_brush.u.color = consume_uint32(&in); + } else if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.fore_brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.fore_brush.u.pattern.pos.x = consume_int32(&in); + out->data.fore_brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + /* back_brush */ { + out->data.back_brush.type = consume_uint8(&in); + if (out->data.back_brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.back_brush.u.color = consume_uint32(&in); + } else if (out->data.back_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.back_brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.back_brush.u.pattern.pos.x = consume_int32(&in); + out->data.back_brush.u.pattern.pos.y = consume_int32(&in); + } + } + } + out->data.fore_mode = consume_uint16(&in); + out->data.back_mode = consume_uint16(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_transparent(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawTransparent *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data__extra_size = data_src_bitmap__extra_size; + } + + nw_size = 28 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawTransparent) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawTransparent); + in = start; + + out = (SpiceMsgDisplayDrawTransparent *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.src_color = consume_uint32(&in); + out->data.true_color = consume_uint32(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_alpha_blend(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__extra_size; + SpiceMsgDisplayDrawAlphaBlend *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 2); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data__extra_size = data_src_bitmap__extra_size; + } + + nw_size = 22 + base__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawAlphaBlend) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawAlphaBlend); + in = start; + + out = (SpiceMsgDisplayDrawAlphaBlend *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + out->data.alpha_flags = consume_uint8(&in); + out->data.alpha = consume_uint8(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_surface_create(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgSurfaceCreate *out; + + nw_size = 20; + mem_size = sizeof(SpiceMsgSurfaceCreate); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgSurfaceCreate); + in = start; + + out = (SpiceMsgSurfaceCreate *)data; + + out->surface_id = consume_uint32(&in); + out->width = consume_uint32(&in); + out->height = consume_uint32(&in); + out->format = consume_uint32(&in); + out->flags = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_surface_destroy(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgSurfaceDestroy *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgSurfaceDestroy); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgSurfaceDestroy); + in = start; + + out = (SpiceMsgSurfaceDestroy *)data; + + out->surface_id = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_data_sized(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgDisplayStreamDataSized *out; + + { /* data */ + uint32_t data_size__value; + pos = start + 32; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + data__nelements = data_size__value; + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 36 + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayStreamDataSized) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamDataSized); + in = start; + + out = (SpiceMsgDisplayStreamDataSized *)data; + + /* base */ { + out->base.id = consume_uint32(&in); + out->base.multi_media_time = consume_uint32(&in); + } + out->width = consume_uint32(&in); + out->height = consume_uint32(&in); + /* dest */ { + out->dest.top = consume_int32(&in); + out->dest.left = consume_int32(&in); + out->dest.bottom = consume_int32(&in); + out->dest.right = consume_int32(&in); + } + out->data_size = consume_uint32(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_monitors_config(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t heads__nw_size, heads__mem_size; + uint32_t heads__nelements; + SpiceMsgDisplayMonitorsConfig *out; + uint32_t i; + + { /* heads */ + uint16_t count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + count__value = read_uint16(pos); + heads__nelements = count__value; + + heads__nw_size = (28) * heads__nelements; + heads__mem_size = sizeof(SpiceHead) * heads__nelements; + } + + nw_size = 4 + heads__nw_size; + mem_size = sizeof(SpiceMsgDisplayMonitorsConfig) + heads__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayMonitorsConfig); + in = start; + + out = (SpiceMsgDisplayMonitorsConfig *)data; + + out->count = consume_uint16(&in); + out->max_allowed = consume_uint16(&in); + for (i = 0; i < heads__nelements; i++) { + SpiceHead *out2; + out2 = (SpiceHead *)end; + end += sizeof(SpiceHead); + + out2->id = consume_uint32(&in); + out2->surface_id = consume_uint32(&in); + out2->width = consume_uint32(&in); + out2->height = consume_uint32(&in); + out2->x = consume_uint32(&in); + out2->y = consume_uint32(&in); + out2->flags = consume_uint32(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_composite(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__nw_size, base__extra_size; + uint32_t rects__saved_size = 0; + size_t data__nw_size, data__extra_size; + SpiceMsgDisplayDrawComposite *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__nw_size, base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20); + size_t base_clip_u__nw_size, base_clip_u__extra_size; + uint8_t type__value; + { /* u */ + uint32_t base_clip_u__mem_size; + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + type__value = read_uint8(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1); + size_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size; + uint32_t base_clip_u_rects__nelements; + { /* rects */ + uint32_t num_rects__value; + pos = start4 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + base_clip_u_rects__nelements = num_rects__value; + + base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements; + base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements; + } + + base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size; + base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size; + rects__saved_size = base_clip_u__nw_size; + base_clip_u__extra_size = base_clip_u__mem_size; + } else { + base_clip_u__nw_size = 0; + base_clip_u__extra_size = 0; + } + + } + + base_clip__nw_size = 1 + base_clip_u__nw_size; + base_clip__extra_size = base_clip_u__extra_size; + } + + base__nw_size = 20 + base_clip__nw_size; + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size); + size_t data_src_bitmap__extra_size; + size_t data_a__nw_size, data_a__extra_size; + uint32_t flags__value; + size_t data_b__nw_size; + size_t data_c__nw_size; + { /* src_bitmap */ + uint32_t src_bitmap__value; + pos = (start2 + 4); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + src_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* a */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + flags__value = read_uint32(pos); + if ((flags__value & SPICE_COMPOSITE_HAS_MASK)) { + uint32_t data_a_mask_bitmap__value; + data_a__nw_size = 4; + pos = (start2 + 8); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_a_mask_bitmap__value = read_uint32(pos); + ptr_size = validate_SpiceImage(message_start, message_end, data_a_mask_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_a__extra_size = ptr_size + /* for alignment */ 3; + } else { + data_a__nw_size = 0; + data_a__extra_size = 0; + } + + } + + { /* b */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + flags__value = read_uint32(pos); + if ((flags__value & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size); + data_b__nw_size = 24; + } else { + data_b__nw_size = 0; + } + + } + + { /* c */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + flags__value = read_uint32(pos); + if ((flags__value & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size + data_b__nw_size); + data_c__nw_size = 24; + } else { + data_c__nw_size = 0; + } + + } + + data__nw_size = 16 + data_a__nw_size + data_b__nw_size + data_c__nw_size; + data__extra_size = data_src_bitmap__extra_size + data_a__extra_size; + } + + nw_size = 0 + base__nw_size + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayDrawComposite) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawComposite); + in = start; + + out = (SpiceMsgDisplayDrawComposite *)data; + + /* base */ { + out->base.surface_id = consume_uint32(&in); + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint8(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = in - start; + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + in += rects__saved_size; + } + } + } + /* data */ { + out->data.flags = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK)) { + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask_bitmap; + n_ptr++; + } + if ((out->data.flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) { + out->data.src_transform.t00 = consume_uint32(&in); + out->data.src_transform.t01 = consume_uint32(&in); + out->data.src_transform.t02 = consume_uint32(&in); + out->data.src_transform.t10 = consume_uint32(&in); + out->data.src_transform.t11 = consume_uint32(&in); + out->data.src_transform.t12 = consume_uint32(&in); + } + if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) { + out->data.mask_transform.t00 = consume_uint32(&in); + out->data.mask_transform.t01 = consume_uint32(&in); + out->data.mask_transform.t02 = consume_uint32(&in); + out->data.mask_transform.t10 = consume_uint32(&in); + out->data.mask_transform.t11 = consume_uint32(&in); + out->data.mask_transform.t12 = consume_uint32(&in); + } + /* src_origin */ { + out->data.src_origin.x = consume_int16(&in); + out->data.src_origin.y = consume_int16(&in); + } + /* mask_origin */ { + out->data.mask_origin.x = consume_int16(&in); + out->data.mask_origin.y = consume_int16(&in); + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_activate_report(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayStreamActivateReport *out; + + nw_size = 16; + mem_size = sizeof(SpiceMsgDisplayStreamActivateReport); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamActivateReport); + in = start; + + out = (SpiceMsgDisplayStreamActivateReport *)data; + + out->stream_id = consume_uint32(&in); + out->unique_id = consume_uint32(&in); + out->max_window_size = consume_uint32(&in); + out->timeout_ms = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_gl_scanout_unix(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayGlScanoutUnix *out; + + nw_size = 20; + mem_size = sizeof(SpiceMsgDisplayGlScanoutUnix); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayGlScanoutUnix); + in = start; + + out = (SpiceMsgDisplayGlScanoutUnix *)data; + + out->drm_dma_buf_fd = consume_fd(&in); + out->width = consume_uint32(&in); + out->height = consume_uint32(&in); + out->stride = consume_uint32(&in); + out->drm_fourcc_format = consume_uint32(&in); + out->flags = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_gl_draw(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayGlDraw *out; + + nw_size = 16; + mem_size = sizeof(SpiceMsgDisplayGlDraw); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayGlDraw); + in = start; + + out = (SpiceMsgDisplayGlDraw *)data; + + out->x = consume_uint32(&in); + out->y = consume_uint32(&in); + out->w = consume_uint32(&in); + out->h = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_DisplayChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[9] = { + parse_SpiceMsgEmpty, + parse_msg_display_mode, + parse_SpiceMsgEmpty, + parse_SpiceMsgEmpty, + parse_msg_display_copy_bits, + parse_msg_display_inval_list, + parse_msg_display_inval_all_pixmaps, + parse_msg_display_inval_palette, + parse_SpiceMsgEmpty + }; + static parse_msg_func_t funcs3[5] = { + parse_msg_display_stream_create, + parse_msg_display_stream_data, + parse_msg_display_stream_clip, + parse_msg_display_stream_destroy, + parse_SpiceMsgEmpty + }; + static parse_msg_func_t funcs4[20] = { + parse_msg_display_draw_fill, + parse_msg_display_draw_opaque, + parse_msg_display_draw_copy, + parse_msg_display_draw_blend, + parse_msg_display_draw_blackness, + parse_msg_display_draw_whiteness, + parse_msg_display_draw_invers, + parse_msg_display_draw_rop3, + parse_msg_display_draw_stroke, + parse_msg_display_draw_text, + parse_msg_display_draw_transparent, + parse_msg_display_draw_alpha_blend, + parse_msg_display_surface_create, + parse_msg_display_surface_destroy, + parse_msg_display_stream_data_sized, + parse_msg_display_monitors_config, + parse_msg_display_draw_composite, + parse_msg_display_stream_activate_report, + parse_msg_display_gl_scanout_unix, + parse_msg_display_gl_draw + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 109) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 122 && message_type < 127) { + return funcs3[message_type-122](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 302 && message_type < 322) { + return funcs4[message_type-302](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_inputs_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgInputsInit *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgInputsInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgInputsInit); + in = start; + + out = (SpiceMsgInputsInit *)data; + + out->keyboard_modifiers = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_inputs_key_modifiers(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgInputsKeyModifiers *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgInputsKeyModifiers); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgInputsKeyModifiers); + in = start; + + out = (SpiceMsgInputsKeyModifiers *)data; + + out->modifiers = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_InputsChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[3] = { + parse_SpiceMsgEmpty, + parse_msg_inputs_init, + parse_msg_inputs_key_modifiers + }; + static parse_msg_func_t funcs3[1] = { + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 103) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 111 && message_type < 112) { + return funcs3[message_type-111](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_cursor_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t cursor__nw_size; + SpiceMsgCursorInit *out; + + { /* cursor */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 9); + size_t cursor_u__nw_size; + uint16_t flags__value; + size_t cursor_data__nw_size; + uint32_t cursor_data__nelements; + { /* u */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + flags__value = read_uint16(pos); + if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2); + cursor_u__nw_size = 17; + } else { + cursor_u__nw_size = 0; + } + + } + + { /* data */ + cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size); + + cursor_data__nw_size = cursor_data__nelements; + } + + cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size; + } + + nw_size = 9 + cursor__nw_size; + mem_size = sizeof(SpiceMsgCursorInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorInit); + in = start; + + out = (SpiceMsgCursorInit *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + out->trail_length = consume_uint16(&in); + out->trail_frequency = consume_uint16(&in); + out->visible = consume_uint8(&in); + /* cursor */ { + uint32_t data__nelements; + out->cursor.flags = consume_uint16(&in); + if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) { + out->cursor.header.unique = consume_uint64(&in); + out->cursor.header.type = consume_uint8(&in); + out->cursor.header.width = consume_uint16(&in); + out->cursor.header.height = consume_uint16(&in); + out->cursor.header.hot_spot_x = consume_uint16(&in); + out->cursor.header.hot_spot_y = consume_uint16(&in); + } + data__nelements = (message_end - in) / (1); + /* use array as pointer */ + out->cursor.data = (uint8_t *)in; + out->cursor.data_size = data__nelements; + in += data__nelements; + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_set(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t cursor__nw_size; + SpiceMsgCursorSet *out; + + { /* cursor */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 5); + size_t cursor_u__nw_size; + uint16_t flags__value; + size_t cursor_data__nw_size; + uint32_t cursor_data__nelements; + { /* u */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + flags__value = read_uint16(pos); + if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) { + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2); + cursor_u__nw_size = 17; + } else { + cursor_u__nw_size = 0; + } + + } + + { /* data */ + cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size); + + cursor_data__nw_size = cursor_data__nelements; + } + + cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size; + } + + nw_size = 5 + cursor__nw_size; + mem_size = sizeof(SpiceMsgCursorSet); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorSet); + in = start; + + out = (SpiceMsgCursorSet *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + out->visible = consume_uint8(&in); + /* cursor */ { + uint32_t data__nelements; + out->cursor.flags = consume_uint16(&in); + if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) { + out->cursor.header.unique = consume_uint64(&in); + out->cursor.header.type = consume_uint8(&in); + out->cursor.header.width = consume_uint16(&in); + out->cursor.header.height = consume_uint16(&in); + out->cursor.header.hot_spot_x = consume_uint16(&in); + out->cursor.header.hot_spot_y = consume_uint16(&in); + } + data__nelements = (message_end - in) / (1); + /* use array as pointer */ + out->cursor.data = (uint8_t *)in; + out->cursor.data_size = data__nelements; + in += data__nelements; + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_move(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgCursorMove *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgCursorMove); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorMove); + in = start; + + out = (SpiceMsgCursorMove *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_trail(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgCursorTrail *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgCursorTrail); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorTrail); + in = start; + + out = (SpiceMsgCursorTrail *)data; + + out->length = consume_uint16(&in); + out->frequency = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_inval_one(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayInvalOne *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgDisplayInvalOne); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayInvalOne); + in = start; + + out = (SpiceMsgDisplayInvalOne *)data; + + out->id = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_CursorChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[9] = { + parse_SpiceMsgEmpty, + parse_msg_cursor_init, + parse_SpiceMsgEmpty, + parse_msg_cursor_set, + parse_msg_cursor_move, + parse_SpiceMsgEmpty, + parse_msg_cursor_trail, + parse_msg_cursor_inval_one, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 109) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_playback_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPlaybackPacket *out; + + { /* data */ + data__nelements = message_end - (start + 4); + + data__nw_size = data__nelements; + } + + nw_size = 4 + data__nw_size; + mem_size = sizeof(SpiceMsgPlaybackPacket); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackPacket); + in = start; + + out = (SpiceMsgPlaybackPacket *)data; + + out->time = consume_uint32(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_playback_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPlaybackMode *out; + + { /* data */ + data__nelements = message_end - (start + 6); + + data__nw_size = data__nelements; + } + + nw_size = 6 + data__nw_size; + mem_size = sizeof(SpiceMsgPlaybackMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackMode); + in = start; + + out = (SpiceMsgPlaybackMode *)data; + + out->time = consume_uint32(&in); + out->mode = consume_uint16(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_playback_start(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgPlaybackStart *out; + + nw_size = 14; + mem_size = sizeof(SpiceMsgPlaybackStart); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackStart); + in = start; + + out = (SpiceMsgPlaybackStart *)data; + + out->channels = consume_uint32(&in); + out->format = consume_uint16(&in); + out->frequency = consume_uint32(&in); + out->time = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SpiceMsgAudioVolume(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t volume__nw_size, volume__mem_size; + uint32_t volume__nelements; + SpiceMsgAudioVolume *out; + uint32_t i; + + { /* volume */ + uint8_t nchannels__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + nchannels__value = read_uint8(pos); + volume__nelements = nchannels__value; + + volume__nw_size = (2) * volume__nelements; + volume__mem_size = sizeof(uint16_t) * volume__nelements; + } + + nw_size = 1 + volume__nw_size; + mem_size = sizeof(SpiceMsgAudioVolume) + volume__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgAudioVolume); + in = start; + + out = (SpiceMsgAudioVolume *)data; + + out->nchannels = consume_uint8(&in); + for (i = 0; i < volume__nelements; i++) { + out->volume[i] = consume_uint16(&in); + end += sizeof(uint16_t); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SpiceMsgAudioMute(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgAudioMute *out; + + nw_size = 1; + mem_size = sizeof(SpiceMsgAudioMute); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgAudioMute); + in = start; + + out = (SpiceMsgAudioMute *)data; + + out->mute = consume_uint8(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_playback_latency(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgPlaybackLatency *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgPlaybackLatency); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackLatency); + in = start; + + out = (SpiceMsgPlaybackLatency *)data; + + out->latency_ms = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_PlaybackChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[8] = { + parse_SpiceMsgEmpty, + parse_msg_playback_data, + parse_msg_playback_mode, + parse_msg_playback_start, + parse_SpiceMsgEmpty, + parse_SpiceMsgAudioVolume, + parse_SpiceMsgAudioMute, + parse_msg_playback_latency + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 108) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_record_start(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgRecordStart *out; + + nw_size = 10; + mem_size = sizeof(SpiceMsgRecordStart); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgRecordStart); + in = start; + + out = (SpiceMsgRecordStart *)data; + + out->channels = consume_uint32(&in); + out->format = consume_uint16(&in); + out->frequency = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_RecordChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[5] = { + parse_SpiceMsgEmpty, + parse_msg_record_start, + parse_SpiceMsgEmpty, + parse_SpiceMsgAudioVolume, + parse_SpiceMsgAudioMute + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 105) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_tunnel_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelInit *out; + + nw_size = 6; + mem_size = sizeof(SpiceMsgTunnelInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelInit); + in = start; + + out = (SpiceMsgTunnelInit *)data; + + out->max_num_of_sockets = consume_uint16(&in); + out->max_socket_data_size = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_service_ip_map(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t virtual_ip__nw_size; + SpiceMsgTunnelServiceIpMap *out; + + { /* virtual_ip */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 4); + size_t virtual_ip_u__nw_size; + uint16_t type__value; + { /* u */ + uint32_t virtual_ip_u__nelements; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + type__value = read_uint16(pos); + if (type__value == SPICE_TUNNEL_IP_TYPE_IPv4) { + virtual_ip_u__nelements = 4; + + virtual_ip_u__nw_size = virtual_ip_u__nelements; + } else { + virtual_ip_u__nw_size = 0; + } + + } + + virtual_ip__nw_size = 2 + virtual_ip_u__nw_size; + } + + nw_size = 4 + virtual_ip__nw_size; + mem_size = sizeof(SpiceMsgTunnelServiceIpMap); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelServiceIpMap); + in = start; + + out = (SpiceMsgTunnelServiceIpMap *)data; + + out->service_id = consume_uint32(&in); + /* virtual_ip */ { + out->virtual_ip.type = consume_uint16(&in); + if (out->virtual_ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) { + uint32_t ipv4__nelements; + ipv4__nelements = 4; + memcpy(out->virtual_ip.u.ipv4, in, ipv4__nelements); + in += ipv4__nelements; + } + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_open(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelSocketOpen *out; + + nw_size = 10; + mem_size = sizeof(SpiceMsgTunnelSocketOpen); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketOpen); + in = start; + + out = (SpiceMsgTunnelSocketOpen *)data; + + out->connection_id = consume_uint16(&in); + out->service_id = consume_uint32(&in); + out->tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_fin(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelSocketFin *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgTunnelSocketFin); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketFin); + in = start; + + out = (SpiceMsgTunnelSocketFin *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_close(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelSocketClose *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgTunnelSocketClose); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketClose); + in = start; + + out = (SpiceMsgTunnelSocketClose *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgTunnelSocketData *out; + + { /* data */ + data__nelements = message_end - (start + 2); + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 2 + data__nw_size; + mem_size = sizeof(SpiceMsgTunnelSocketData) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketData); + in = start; + + out = (SpiceMsgTunnelSocketData *)data; + + out->connection_id = consume_uint16(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_closed_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelSocketClosedAck *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgTunnelSocketClosedAck); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketClosedAck); + in = start; + + out = (SpiceMsgTunnelSocketClosedAck *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_tunnel_socket_token(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgTunnelSocketTokens *out; + + nw_size = 6; + mem_size = sizeof(SpiceMsgTunnelSocketTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgTunnelSocketTokens); + in = start; + + out = (SpiceMsgTunnelSocketTokens *)data; + + out->connection_id = consume_uint16(&in); + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_TunnelChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[9] = { + parse_SpiceMsgEmpty, + parse_msg_tunnel_init, + parse_msg_tunnel_service_ip_map, + parse_msg_tunnel_socket_open, + parse_msg_tunnel_socket_fin, + parse_msg_tunnel_socket_close, + parse_msg_tunnel_socket_data, + parse_msg_tunnel_socket_closed_ack, + parse_msg_tunnel_socket_token + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 109) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + +#ifdef USE_SMARTCARD + +static uint8_t * parse_msg_smartcard_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgSmartcard *out; + + { /* data */ + uint32_t length__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + length__value = read_uint32(pos); + data__nelements = length__value; + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 12 + data__nw_size; + mem_size = sizeof(SpiceMsgSmartcard) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgSmartcard); + in = start; + + out = (SpiceMsgSmartcard *)data; + + out->type = consume_uint32(&in); + out->reader_id = consume_uint32(&in); + out->length = consume_uint32(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SmartcardChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[2] = { + parse_SpiceMsgEmpty, + parse_msg_smartcard_data + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 102) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} +#endif /* USE_SMARTCARD */ + + + +static uint8_t * parse_UsbredirChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[2] = { + parse_SpiceMsgEmpty, + parse_SpiceMsgData + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 102) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_port_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t name__extra_size; + uint32_t name__array__nelements; + SpiceMsgPortInit *out; + uint32_t i; + + { /* name */ + uint32_t name__value; + uint32_t name__array__nw_size; + uint32_t name__array__mem_size; + uint32_t name_size__value; + pos = (start + 4); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + name__value = read_uint32(pos); + if (SPICE_UNLIKELY(name__value == 0)) { + goto error; + } + if (SPICE_UNLIKELY(message_start + name__value >= message_end)) { + goto error; + } + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + name_size__value = read_uint32(pos); + name__array__nelements = name_size__value; + + name__array__nw_size = name__array__nelements; + name__array__mem_size = sizeof(uint8_t) * name__array__nelements; + if (SPICE_UNLIKELY(message_start + name__value + name__array__nw_size > message_end)) { + goto error; + } + name__extra_size = name__array__mem_size + /* for alignment */ 3; + } + + nw_size = 9; + mem_size = sizeof(SpiceMsgPortInit) + name__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPortInit); + in = start; + + out = (SpiceMsgPortInit *)data; + + out->name_size = consume_uint32(&in); + ptr_info[n_ptr].offset = consume_uint32(&in); + ptr_info[n_ptr].parse = parse_array_uint8; + ptr_info[n_ptr].dest = (void **)&out->name; + ptr_info[n_ptr].nelements = name__array__nelements; + n_ptr++; + out->opened = consume_uint8(&in); + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_port_event(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgPortEvent *out; + + nw_size = 1; + mem_size = sizeof(SpiceMsgPortEvent); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPortEvent); + in = start; + + out = (SpiceMsgPortEvent *)data; + + out->event = consume_uint8(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_PortChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[2] = { + parse_SpiceMsgEmpty, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs3[2] = { + parse_msg_port_init, + parse_msg_port_event + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 102) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 201 && message_type < 203) { + return funcs3[message_type-201](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_WebDAVChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[8] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs2[2] = { + parse_SpiceMsgEmpty, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs3[2] = { + parse_msg_port_init, + parse_msg_port_event + }; + if (message_type >= 1 && message_type < 9) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 100 && message_type < 102) { + return funcs2[message_type-100](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 201 && message_type < 203) { + return funcs3[message_type-201](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + +spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type) +{ + static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[12] = { + { NULL, 0 }, + { parse_MainChannel_msg, 118}, + { parse_DisplayChannel_msg, 321}, + { parse_InputsChannel_msg, 111}, + { parse_CursorChannel_msg, 108}, + { parse_PlaybackChannel_msg, 107}, + { parse_RecordChannel_msg, 104}, + { parse_TunnelChannel_msg, 108}, +#ifdef USE_SMARTCARD + { parse_SmartcardChannel_msg, 101}, +#else /* USE_SMARTCARD */ + { NULL, 0 }, +#endif /* USE_SMARTCARD */ + { parse_UsbredirChannel_msg, 101}, + { parse_PortChannel_msg, 202}, + { parse_WebDAVChannel_msg, 202} + }; + if (channel < 12) { + if (max_message_type != NULL) { + *max_message_type = channels[channel].max_messages; + } + return channels[channel].func; + } + return NULL; +} + +uint8_t * spice_parse_msg(uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + spice_parse_channel_func_t func; + func = spice_get_server_channel_parser(channel, NULL); + if (func != NULL) { + return func(message_start, message_end, message_type, minor, size_out, free_message); + } + return NULL; +} diff --git a/spice-common/common/generated_client_demarshallers1.c b/spice-common/common/generated_client_demarshallers1.c new file mode 100644 index 0000000..19478a9 --- /dev/null +++ b/spice-common/common/generated_client_demarshallers1.c @@ -0,0 +1,5882 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#endif + + + +#ifdef WORDS_BIGENDIAN +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) *(int8_t *)(ptr) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) *(uint8_t *)(ptr) = val +#define read_int16(ptr) ((int16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_int16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_uint16(ptr) ((uint16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_uint16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_int32(ptr) ((int32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_int32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_uint32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_int64(ptr) ((int64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_int64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#define read_uint64(ptr) ((uint64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_uint64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#else +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) (*((int8_t *)(ptr))) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) (*((uint8_t *)(ptr))) = val +#define read_int16(ptr) (*((int16_t *)(ptr))) +#define write_int16(ptr, val) (*((int16_t *)(ptr))) = val +#define read_uint16(ptr) (*((uint16_t *)(ptr))) +#define write_uint16(ptr, val) (*((uint16_t *)(ptr))) = val +#define read_int32(ptr) (*((int32_t *)(ptr))) +#define write_int32(ptr, val) (*((int32_t *)(ptr))) = val +#define read_uint32(ptr) (*((uint32_t *)(ptr))) +#define write_uint32(ptr, val) (*((uint32_t *)(ptr))) = val +#define read_int64(ptr) (*((int64_t *)(ptr))) +#define write_int64(ptr, val) (*((int64_t *)(ptr))) = val +#define read_uint64(ptr) (*((uint64_t *)(ptr))) +#define write_uint64(ptr, val) (*((uint64_t *)(ptr))) = val +#endif + +static int8_t SPICE_GNUC_UNUSED consume_int8(uint8_t **ptr) +{ + int8_t val; + val = read_int8(*ptr); + *ptr += 1; + return val; +} + +static uint8_t SPICE_GNUC_UNUSED consume_uint8(uint8_t **ptr) +{ + uint8_t val; + val = read_uint8(*ptr); + *ptr += 1; + return val; +} + +static int16_t SPICE_GNUC_UNUSED consume_int16(uint8_t **ptr) +{ + int16_t val; + val = read_int16(*ptr); + *ptr += 2; + return val; +} + +static uint16_t SPICE_GNUC_UNUSED consume_uint16(uint8_t **ptr) +{ + uint16_t val; + val = read_uint16(*ptr); + *ptr += 2; + return val; +} + +static int32_t SPICE_GNUC_UNUSED consume_int32(uint8_t **ptr) +{ + int32_t val; + val = read_int32(*ptr); + *ptr += 4; + return val; +} + +static uint32_t SPICE_GNUC_UNUSED consume_uint32(uint8_t **ptr) +{ + uint32_t val; + val = read_uint32(*ptr); + *ptr += 4; + return val; +} + +static int64_t SPICE_GNUC_UNUSED consume_int64(uint8_t **ptr) +{ + int64_t val; + val = read_int64(*ptr); + *ptr += 8; + return val; +} + +static uint64_t SPICE_GNUC_UNUSED consume_uint64(uint8_t **ptr) +{ + uint64_t val; + val = read_uint64(*ptr); + *ptr += 8; + return val; +} +static int SPICE_GNUC_UNUSED consume_fd(uint8_t **ptr) +{ + return -1; +} + +typedef struct PointerInfo PointerInfo; +typedef void (*message_destructor_t)(uint8_t *message); +typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor); +typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message); +typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message); + +struct PointerInfo { + uint64_t offset; + parse_func_t parse; + void * *dest; + uint32_t nelements; +}; + +static uint8_t * parse_msg_migrate(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMigrate *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMigrate); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMigrate); + in = start; + + out = (SpiceMsgMigrate *)data; + + out->flags = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static void nofree(SPICE_GNUC_UNUSED uint8_t *data) +{ +} + +static uint8_t * parse_SpiceMsgData(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t data__nw_size; + uint32_t data__nelements; + + { /* data */ + data__nelements = message_end - (start + 0); + + data__nw_size = data__nelements; + } + + nw_size = 0 + data__nw_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = message_start; + *size = message_end - message_start; + *free_message = nofree; + return data; + +} + +static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgSetAck *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgSetAck); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgSetAck); + in = start; + + out = (SpiceMsgSetAck *)data; + + out->generation = consume_uint32(&in); + out->window = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_ping(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPing *out; + + { /* data */ + data__nelements = message_end - (start + 12); + + data__nw_size = data__nelements; + } + + nw_size = 12 + data__nw_size; + mem_size = sizeof(SpiceMsgPing); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPing); + in = start; + + out = (SpiceMsgPing *)data; + + out->id = consume_uint32(&in); + out->timestamp = consume_uint64(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_len = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_wait_for_channels(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t wait_list__nw_size, wait_list__mem_size; + uint32_t wait_list__nelements; + SpiceMsgWaitForChannels *out; + uint32_t i; + + { /* wait_list */ + uint8_t wait_count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + wait_count__value = read_uint8(pos); + wait_list__nelements = wait_count__value; + + wait_list__nw_size = (10) * wait_list__nelements; + wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements; + } + + nw_size = 1 + wait_list__nw_size; + mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgWaitForChannels); + in = start; + + out = (SpiceMsgWaitForChannels *)data; + + out->wait_count = consume_uint8(&in); + for (i = 0; i < wait_list__nelements; i++) { + SpiceWaitForChannel *out2; + out2 = (SpiceWaitForChannel *)end; + end += sizeof(SpiceWaitForChannel); + + out2->channel_type = consume_uint8(&in); + out2->channel_id = consume_uint8(&in); + out2->message_serial = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_disconnecting(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisconnect *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgDisconnect); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisconnect); + in = start; + + out = (SpiceMsgDisconnect *)data; + + out->time_stamp = consume_uint64(&in); + out->reason = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_notify(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t message__nw_size, message__mem_size; + uint32_t message__nelements; + size_t zero__mem_size; + SpiceMsgNotify *out; + + { /* message */ + uint32_t message_len__value; + pos = start + 20; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + message_len__value = read_uint32(pos); + message__nelements = message_len__value; + + message__nw_size = message__nelements; + message__mem_size = sizeof(uint8_t) * message__nelements; + } + + { /* zero */ + zero__mem_size = sizeof(uint8_t); + } + + nw_size = 25 + message__nw_size; + mem_size = sizeof(SpiceMsgNotify) + message__mem_size + zero__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgNotify); + in = start; + + out = (SpiceMsgNotify *)data; + + out->time_stamp = consume_uint64(&in); + out->severity = consume_uint32(&in); + out->visibilty = consume_uint32(&in); + out->what = consume_uint32(&in); + out->message_len = consume_uint32(&in); + memcpy(out->message, in, message__nelements); + in += message__nelements; + end += message__nelements; + *(uint8_t *)end = consume_uint8(&in); + end += sizeof(uint8_t); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_migrate_begin(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t dst_info__nw_size; + SpiceMsgMainMigrationBegin *out; + + { /* dst_info */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t dst_info_host_data__nw_size; + uint32_t dst_info_host_data__nelements; + size_t dst_info_pub_key_data__nw_size; + uint32_t dst_info_pub_key_data__nelements; + { /* host_data */ + uint32_t host_size__value; + pos = start2 + 8; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_size__value = read_uint32(pos); + dst_info_host_data__nelements = host_size__value; + + dst_info_host_data__nw_size = dst_info_host_data__nelements; + } + + if (minor >= 1) { /* pub_key_data */ + uint32_t pub_key_size__value; + pos = start2 + 12 + ((minor >= 1)?6:0); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + pub_key_size__value = read_uint32(pos); + dst_info_pub_key_data__nelements = pub_key_size__value; + + dst_info_pub_key_data__nw_size = dst_info_pub_key_data__nelements; + } else { /* minor < 1 */ + dst_info_pub_key_data__nelements = 0; + dst_info_pub_key_data__nw_size = 0; + } + + dst_info__nw_size = 12 + ((minor >= 1)?10:0) + dst_info_host_data__nw_size + dst_info_pub_key_data__nw_size; + } + + nw_size = 0 + dst_info__nw_size; + mem_size = sizeof(SpiceMsgMainMigrationBegin); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMigrationBegin); + in = start; + + out = (SpiceMsgMainMigrationBegin *)data; + + /* dst_info */ { + uint32_t host_data__nelements; + uint32_t pub_key_data__nelements; + out->dst_info.port = consume_uint16(&in); + out->dst_info.sport = consume_uint16(&in); + consume_uint32(&in); + out->dst_info.host_size = consume_uint32(&in); + if (minor >= 1) { + out->dst_info.pub_key_type = consume_uint16(&in); + } else { + out->dst_info.pub_key_type = 0; + } + if (minor >= 1) { + consume_uint32(&in); + } else { + } + if (minor >= 1) { + out->dst_info.pub_key_size = consume_uint32(&in); + } else { + out->dst_info.pub_key_size = 0; + } + host_data__nelements = out->dst_info.host_size; + /* use array as pointer */ + out->dst_info.host_data = (uint8_t *)in; + in += host_data__nelements; + if (minor >= 1) { + pub_key_data__nelements = out->dst_info.pub_key_size; + /* use array as pointer */ + out->dst_info.pub_key_data = (uint8_t *)in; + in += pub_key_data__nelements; + } + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SpiceMsgEmpty(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + + nw_size = 0; + mem_size = sizeof(SpiceMsgEmpty); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgEmpty); + in = start; + + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainInit *out; + + nw_size = 32; + mem_size = sizeof(SpiceMsgMainInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainInit); + in = start; + + out = (SpiceMsgMainInit *)data; + + out->session_id = consume_uint32(&in); + out->display_channels_hint = consume_uint32(&in); + out->supported_mouse_modes = consume_uint32(&in); + out->current_mouse_mode = consume_uint32(&in); + out->agent_connected = consume_uint32(&in); + out->agent_tokens = consume_uint32(&in); + out->multi_media_time = consume_uint32(&in); + out->ram_hint = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_channels_list(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t channels__nw_size, channels__mem_size; + uint32_t channels__nelements; + SpiceMsgChannels *out; + uint32_t i; + + { /* channels */ + uint32_t num_of_channels__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_of_channels__value = read_uint32(pos); + channels__nelements = num_of_channels__value; + + channels__nw_size = (2) * channels__nelements; + channels__mem_size = sizeof(SpiceChannelId) * channels__nelements; + } + + nw_size = 4 + channels__nw_size; + mem_size = sizeof(SpiceMsgChannels) + channels__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgChannels); + in = start; + + out = (SpiceMsgChannels *)data; + + out->num_of_channels = consume_uint32(&in); + for (i = 0; i < channels__nelements; i++) { + SpiceChannelId *out2; + out2 = (SpiceChannelId *)end; + end += sizeof(SpiceChannelId); + + out2->type = consume_uint8(&in); + out2->id = consume_uint8(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_mouse_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainMouseMode *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgMainMouseMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMouseMode); + in = start; + + out = (SpiceMsgMainMouseMode *)data; + + out->supported_modes = consume_uint32(&in); + out->current_mode = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_multi_media_time(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainMultiMediaTime *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainMultiMediaTime); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMultiMediaTime); + in = start; + + out = (SpiceMsgMainMultiMediaTime *)data; + + out->time = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_agent_disconnected(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainAgentDisconnect *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainAgentDisconnect); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainAgentDisconnect); + in = start; + + out = (SpiceMsgMainAgentDisconnect *)data; + + out->error_code = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_agent_token(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgMainAgentTokens *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgMainAgentTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainAgentTokens); + in = start; + + out = (SpiceMsgMainAgentTokens *)data; + + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_main_migrate_switch_host(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t host_data__nw_size; + uint32_t host_data__nelements; + size_t cert_subject_data__nw_size; + uint32_t cert_subject_data__nelements; + SpiceMsgMainMigrationSwitchHost *out; + + { /* host_data */ + uint32_t host_size__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + host_size__value = read_uint32(pos); + host_data__nelements = host_size__value; + + host_data__nw_size = host_data__nelements; + } + + { /* cert_subject_data */ + uint32_t cert_subject_size__value; + pos = start + 16; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + cert_subject_size__value = read_uint32(pos); + cert_subject_data__nelements = cert_subject_size__value; + + cert_subject_data__nw_size = cert_subject_data__nelements; + } + + nw_size = 20 + host_data__nw_size + cert_subject_data__nw_size; + mem_size = sizeof(SpiceMsgMainMigrationSwitchHost); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgMainMigrationSwitchHost); + in = start; + + out = (SpiceMsgMainMigrationSwitchHost *)data; + + out->port = consume_uint16(&in); + out->sport = consume_uint16(&in); + consume_uint32(&in); + out->host_size = consume_uint32(&in); + consume_uint32(&in); + out->cert_subject_size = consume_uint32(&in); + /* use array as pointer */ + out->host_data = (uint8_t *)in; + in += host_data__nelements; + /* use array as pointer */ + out->cert_subject_data = (uint8_t *)in; + in += cert_subject_data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_MainChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[11] = { + parse_msg_main_migrate_begin, + parse_SpiceMsgEmpty, + parse_msg_main_init, + parse_msg_main_channels_list, + parse_msg_main_mouse_mode, + parse_msg_main_multi_media_time, + parse_SpiceMsgEmpty, + parse_msg_main_agent_disconnected, + parse_SpiceMsgData, + parse_msg_main_agent_token, + parse_msg_main_migrate_switch_host + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 112) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_display_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayMode *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgDisplayMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayMode); + in = start; + + out = (SpiceMsgDisplayMode *)data; + + out->x_res = consume_uint32(&in); + out->y_res = consume_uint32(&in); + out->bits = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpiceClipRects(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t rects__nw_size, rects__mem_size; + uint32_t rects__nelements; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* rects */ + uint32_t num_rects__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + num_rects__value = read_uint32(pos); + rects__nelements = num_rects__value; + + rects__nw_size = (16) * rects__nelements; + rects__mem_size = sizeof(SpiceRect) * rects__nelements; + } + + nw_size = 4 + rects__nw_size; + mem_size = sizeof(SpiceClipRects) + rects__mem_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpiceClipRects(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpiceClipRects *out; + uint32_t rects__nelements; + uint32_t i; + + end = struct_data + sizeof(SpiceClipRects); + out = (SpiceClipRects *)struct_data; + + out->num_rects = consume_uint32(&in); + rects__nelements = out->num_rects; + for (i = 0; i < rects__nelements; i++) { + SpiceRect *out2; + out2 = (SpiceRect *)end; + end += sizeof(SpiceRect); + + out2->top = consume_int32(&in); + out2->left = consume_int32(&in); + out2->bottom = consume_int32(&in); + out2->right = consume_int32(&in); + } + return end; +} + +static uint8_t * parse_msg_display_copy_bits(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t base__extra_size; + SpiceMsgDisplayCopyBits *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + nw_size = 36; + mem_size = sizeof(SpiceMsgDisplayCopyBits) + base__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayCopyBits); + in = start; + + out = (SpiceMsgDisplayCopyBits *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* src_pos */ { + out->src_pos.x = consume_int32(&in); + out->src_pos.y = consume_int32(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_list(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t resources__nw_size, resources__mem_size; + uint32_t resources__nelements; + SpiceResourceList *out; + uint32_t i; + + { /* resources */ + uint16_t count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + count__value = read_uint16(pos); + resources__nelements = count__value; + + resources__nw_size = (9) * resources__nelements; + resources__mem_size = sizeof(SpiceResourceID) * resources__nelements; + } + + nw_size = 2 + resources__nw_size; + mem_size = sizeof(SpiceResourceList) + resources__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceResourceList); + in = start; + + out = (SpiceResourceList *)data; + + out->count = consume_uint16(&in); + for (i = 0; i < resources__nelements; i++) { + SpiceResourceID *out2; + out2 = (SpiceResourceID *)end; + end += sizeof(SpiceResourceID); + + out2->type = consume_uint8(&in); + out2->id = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_all_pixmaps(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t wait_list__nw_size, wait_list__mem_size; + uint32_t wait_list__nelements; + SpiceMsgWaitForChannels *out; + uint32_t i; + + { /* wait_list */ + uint8_t wait_count__value; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + wait_count__value = read_uint8(pos); + wait_list__nelements = wait_count__value; + + wait_list__nw_size = (10) * wait_list__nelements; + wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements; + } + + nw_size = 1 + wait_list__nw_size; + mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgWaitForChannels); + in = start; + + out = (SpiceMsgWaitForChannels *)data; + + out->wait_count = consume_uint8(&in); + for (i = 0; i < wait_list__nelements; i++) { + SpiceWaitForChannel *out2; + out2 = (SpiceWaitForChannel *)end; + end += sizeof(SpiceWaitForChannel); + + out2->channel_type = consume_uint8(&in); + out2->channel_id = consume_uint8(&in); + out2->message_serial = consume_uint64(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_inval_palette(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayInvalOne *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgDisplayInvalOne); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayInvalOne); + in = start; + + out = (SpiceMsgDisplayInvalOne *)data; + + out->id = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_create(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t clip__extra_size; + SpiceMsgDisplayStreamCreate *out; + uint32_t i; + + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 52); + size_t clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t clip_u_rects__value; + pos = (start2 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + clip_u__extra_size = 0; + } else { + clip_u__extra_size = 0; + } + + } + + clip__extra_size = clip_u__extra_size; + } + + nw_size = 64; + mem_size = sizeof(SpiceMsgDisplayStreamCreate) + clip__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamCreate); + in = start; + + out = (SpiceMsgDisplayStreamCreate *)data; + + out->surface_id = 0; + out->id = consume_uint32(&in); + out->flags = consume_uint32(&in); + out->codec_type = consume_uint32(&in); + out->stamp = consume_uint64(&in); + out->stream_width = consume_uint32(&in); + out->stream_height = consume_uint32(&in); + out->src_width = consume_uint32(&in); + out->src_height = consume_uint32(&in); + /* dest */ { + out->dest.top = consume_int32(&in); + out->dest.left = consume_int32(&in); + out->dest.bottom = consume_int32(&in); + out->dest.right = consume_int32(&in); + } + /* clip */ { + out->clip.type = consume_uint32(&in); + if (out->clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgDisplayStreamData *out; + + { /* data */ + uint32_t data_size__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + data__nelements = data_size__value; + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 16 + data__nw_size; + mem_size = sizeof(SpiceMsgDisplayStreamData) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamData); + in = start; + + out = (SpiceMsgDisplayStreamData *)data; + + /* base */ { + out->base.id = consume_uint32(&in); + out->base.multi_media_time = consume_uint32(&in); + } + out->data_size = consume_uint32(&in); + consume_uint32(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_clip(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[1]; + size_t clip__extra_size; + SpiceMsgDisplayStreamClip *out; + uint32_t i; + + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 4); + size_t clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t clip_u_rects__value; + pos = (start2 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + clip_u__extra_size = 0; + } else { + clip_u__extra_size = 0; + } + + } + + clip__extra_size = clip_u__extra_size; + } + + nw_size = 16; + mem_size = sizeof(SpiceMsgDisplayStreamClip) + clip__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamClip); + in = start; + + out = (SpiceMsgDisplayStreamClip *)data; + + out->id = consume_uint32(&in); + /* clip */ { + out->clip.type = consume_uint32(&in); + if (out->clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_stream_destroy(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayStreamDestroy *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgDisplayStreamDestroy); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayStreamDestroy); + in = start; + + out = (SpiceMsgDisplayStreamDestroy *)data; + + out->id = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpicePalette(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t ents__nw_size, ents__mem_size; + uint32_t ents__nelements; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* ents */ + uint16_t num_ents__value; + pos = start + 8; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + num_ents__value = read_uint16(pos); + ents__nelements = num_ents__value; + + ents__nw_size = (4) * ents__nelements; + ents__mem_size = sizeof(uint32_t) * ents__nelements; + } + + nw_size = 10 + ents__nw_size; + mem_size = sizeof(SpicePalette) + ents__mem_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static intptr_t validate_SpiceImage(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + SPICE_GNUC_UNUSED intptr_t ptr_size; + size_t u__nw_size, u__extra_size; + uint8_t descriptor_type__value; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* u */ + pos = start + 8; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + descriptor_type__value = read_uint8(pos); + if (descriptor_type__value == SPICE_IMAGE_TYPE_BITMAP) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_pal__extra_size; + uint8_t flags__value; + size_t u_data__extra_size; + uint32_t u_data__array__nelements; + { /* pal */ + pos = start2 + 1; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + u_pal__extra_size = 0; + } else if (1) { + uint64_t u_pal_palette__value; + pos = (start2 + 14); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + u_pal_palette__value = read_uint64(pos); + ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + u_pal__extra_size = ptr_size + /* for alignment */ 3; + } else { + u_pal__extra_size = 0; + } + + } + + { /* data */ + uint64_t data__value; + uint32_t u_data__array__nw_size; + uint32_t stride__value; + uint32_t y__value; + pos = (start2 + 22); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + data__value = read_uint64(pos); + if (SPICE_UNLIKELY(message_start + data__value >= message_end)) { + goto error; + } + pos = start2 + 10; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + stride__value = read_uint32(pos); + pos = start2 + 6; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + y__value = read_uint32(pos); + u_data__array__nelements = stride__value * y__value; + + u_data__array__nw_size = u_data__array__nelements; + if (SPICE_UNLIKELY(message_start + data__value + u_data__array__nw_size > message_end)) { + goto error; + } + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 30; + u__extra_size = u_pal__extra_size + u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_QUIC) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_RGB || descriptor_type__value == SPICE_IMAGE_TYPE_GLZ_RGB) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* data */ + uint32_t data_size__value; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 4 + u_data__nw_size; + u__extra_size = u_data__extra_size; + } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_PLT) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18); + size_t u_pal__extra_size; + uint8_t flags__value; + size_t u_data__nw_size, u_data__extra_size; + uint32_t u_data__nelements; + { /* pal */ + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + flags__value = read_uint8(pos); + if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + u_pal__extra_size = 0; + } else if (1) { + uint64_t u_pal_palette__value; + pos = (start2 + 5); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + u_pal_palette__value = read_uint64(pos); + if (SPICE_UNLIKELY(u_pal_palette__value == 0)) { + goto error; + } + ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + u_pal__extra_size = ptr_size + /* for alignment */ 3; + } else { + u_pal__extra_size = 0; + } + + } + + { /* data */ + uint32_t data_size__value; + pos = start2 + 1; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + data_size__value = read_uint32(pos); + u_data__nelements = data_size__value; + + u_data__nw_size = u_data__nelements; + u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk); + } + + u__nw_size = 13 + u_data__nw_size; + u__extra_size = u_pal__extra_size + u_data__extra_size; + } else { + u__nw_size = 0; + u__extra_size = 0; + } + + } + + nw_size = 18 + u__nw_size; + mem_size = sizeof(SpiceImage) + u__extra_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpicePalette(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpicePalette *out; + uint32_t ents__nelements; + uint32_t i; + + end = struct_data + sizeof(SpicePalette); + out = (SpicePalette *)struct_data; + + out->unique = consume_uint64(&in); + out->num_ents = consume_uint16(&in); + ents__nelements = out->num_ents; + for (i = 0; i < ents__nelements; i++) { + out->ents[i] = consume_uint32(&in); + end += sizeof(uint32_t); + } + return end; +} + +static uint8_t * parse_struct_SpiceImage(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + SpiceImage *out; + uint32_t i; + + end = struct_data + sizeof(SpiceImage); + out = (SpiceImage *)struct_data; + + /* descriptor */ { + out->descriptor.id = consume_uint64(&in); + out->descriptor.type = consume_uint8(&in); + out->descriptor.flags = consume_uint8(&in); + out->descriptor.width = consume_uint32(&in); + out->descriptor.height = consume_uint32(&in); + } + if (out->descriptor.type == SPICE_IMAGE_TYPE_BITMAP) { + uint32_t data__array__nelements; + SpiceChunks *chunks; + out->u.bitmap.format = consume_uint8(&in); + out->u.bitmap.flags = consume_uint8(&in); + out->u.bitmap.x = consume_uint32(&in); + out->u.bitmap.y = consume_uint32(&in); + out->u.bitmap.stride = consume_uint32(&in); + if ((out->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + out->u.bitmap.palette_id = consume_uint64(&in); + } else if (1) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePalette; + ptr_info[n_ptr].dest = (void **)&out->u.bitmap.palette; + n_ptr++; + } + data__array__nelements = out->u.bitmap.stride * out->u.bitmap.y; + /* Reuse data from network message as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.bitmap.data = chunks; + chunks->data_size = data__array__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__array__nelements; + chunks->chunk[0].data = message_start + consume_uint64(&in); + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_QUIC) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.quic.data_size = consume_uint32(&in); + data__nelements = out->u.quic.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.quic.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB || out->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.lz_rgb.data_size = consume_uint32(&in); + data__nelements = out->u.lz_rgb.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.lz_rgb.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { + uint32_t data__nelements; + SpiceChunks *chunks; + out->u.lz_plt.flags = consume_uint8(&in); + out->u.lz_plt.data_size = consume_uint32(&in); + if ((out->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + out->u.lz_plt.palette_id = consume_uint64(&in); + } else if (1) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePalette; + ptr_info[n_ptr].dest = (void **)&out->u.lz_plt.palette; + n_ptr++; + } + data__nelements = out->u.lz_plt.data_size; + /* use array as chunk */ + chunks = (SpiceChunks *)end; + end += sizeof(SpiceChunks) + sizeof(SpiceChunk); + out->u.lz_plt.data = chunks; + chunks->data_size = data__nelements; + chunks->flags = 0; + chunks->num_chunks = 1; + chunks->chunk[0].len = data__nelements; + chunks->chunk[0].data = in; + in += data__nelements; + } + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + return end; + + error: + return NULL; +} + +static uint8_t * parse_msg_display_draw_fill(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawFill *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_brush__extra_size; + size_t data_mask__extra_size; + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__extra_size = 0; + } + + } + + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 22); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 67; + mem_size = sizeof(SpiceMsgDisplayDrawFill) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawFill); + in = start; + + out = (SpiceMsgDisplayDrawFill *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + /* brush */ { + uint8_t *in_save; + out->data.brush.type = consume_uint32(&in); + in_save = in; + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + out->data.rop_descriptor = consume_uint16(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_opaque(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawOpaque *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + size_t data_brush__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 24); + size_t data_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__extra_size = 0; + } + + } + + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 47); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 92; + mem_size = sizeof(SpiceMsgDisplayDrawOpaque) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawOpaque); + in = start; + + out = (SpiceMsgDisplayDrawOpaque *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + /* brush */ { + uint8_t *in_save; + out->data.brush.type = consume_uint32(&in); + in_save = in; + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_copy(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawCopy *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 27); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size; + } + + nw_size = 72; + mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawCopy); + in = start; + + out = (SpiceMsgDisplayDrawCopy *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_blend(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[3]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawBlend *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 27); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size; + } + + nw_size = 72; + mem_size = sizeof(SpiceMsgDisplayDrawBlend) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawBlend); + in = start; + + out = (SpiceMsgDisplayDrawBlend *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.rop_descriptor = consume_uint16(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_blackness(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawBlackness *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 45; + mem_size = sizeof(SpiceMsgDisplayDrawBlackness) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawBlackness); + in = start; + + out = (SpiceMsgDisplayDrawBlackness *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_whiteness(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawWhiteness *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 45; + mem_size = sizeof(SpiceMsgDisplayDrawWhiteness) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawWhiteness); + in = start; + + out = (SpiceMsgDisplayDrawWhiteness *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_invers(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawInvers *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_mask__extra_size; + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_mask__extra_size; + } + + nw_size = 45; + mem_size = sizeof(SpiceMsgDisplayDrawInvers) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawInvers); + in = start; + + out = (SpiceMsgDisplayDrawInvers *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_rop3(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawRop3 *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + size_t data_brush__extra_size; + size_t data_mask__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 24); + size_t data_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__extra_size = 0; + } + + } + + data_brush__extra_size = data_brush_u__extra_size; + } + + { /* mask */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 46); + size_t data_mask_bitmap__extra_size; + { /* bitmap */ + uint64_t bitmap__value; + pos = (start3 + 9); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data_mask__extra_size = data_mask_bitmap__extra_size; + } + + data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size; + } + + nw_size = 91; + mem_size = sizeof(SpiceMsgDisplayDrawRop3) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawRop3); + in = start; + + out = (SpiceMsgDisplayDrawRop3 *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + /* brush */ { + uint8_t *in_save; + out->data.brush.type = consume_uint32(&in); + in_save = in; + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + out->data.rop3 = consume_uint8(&in); + out->data.scale_mode = consume_uint8(&in); + /* mask */ { + out->data.mask.flags = consume_uint8(&in); + /* pos */ { + out->data.mask.pos.x = consume_int32(&in); + out->data.mask.pos.y = consume_int32(&in); + } + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap; + n_ptr++; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpicePath(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t segments__nw_size, segments__mem_size; + uint32_t segments__nelements; + uint32_t segments__nbytes; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* segments */ + uint32_t segments_size__value; + uint8_t *start2 = (start + 4); + uint8_t *start2_array_end; + uint32_t segments__element__nw_size; + uint32_t segments__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + segments_size__value = read_uint32(pos); + segments__nbytes = segments_size__value; + segments__nelements = 0; + + segments__nw_size = segments__nbytes; + segments__mem_size = 0; + start2_array_end = start2 + segments__nbytes; + while (start2 < start2_array_end) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t segments__element_points__nw_size, segments__element_points__mem_size; + uint32_t segments__element_points__nelements; + segments__nelements += 1; + { /* points */ + uint32_t count__value; + pos = start3 + 4; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + count__value = read_uint32(pos); + segments__element_points__nelements = count__value; + + segments__element_points__nw_size = (8) * segments__element_points__nelements; + segments__element_points__mem_size = sizeof(SpicePointFix) * segments__element_points__nelements; + } + + segments__element__nw_size = 8 + segments__element_points__nw_size; + segments__element__mem_size = sizeof(SpicePathSeg) + segments__element_points__mem_size; + segments__mem_size += sizeof(void *) + SPICE_ALIGN(segments__element__mem_size, 4); + start2 += segments__element__nw_size; + } + if (SPICE_UNLIKELY(start2 != start2_array_end)) { + goto error; + } + pos = start + 0; + write_uint32(pos, segments__nelements); + } + + nw_size = 4 + segments__nw_size; + mem_size = sizeof(SpicePath) + segments__mem_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpicePath(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpicePath *out; + uint32_t segments__nelements; + uint32_t i; + void * *ptr_array; + int ptr_array_index; + uint32_t j; + + end = struct_data + sizeof(SpicePath); + out = (SpicePath *)struct_data; + + out->num_segments = consume_uint32(&in); + segments__nelements = out->num_segments; + ptr_array_index = 0; + ptr_array = (void **)out->segments; + end += sizeof(void *) * segments__nelements; + for (i = 0; i < segments__nelements; i++) { + SpicePathSeg *out2; + uint32_t points__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpicePathSeg *)end; + end += sizeof(SpicePathSeg); + + out2->flags = consume_uint32(&in); + out2->count = consume_uint32(&in); + points__nelements = out2->count; + for (j = 0; j < points__nelements; j++) { + SpicePointFix *out3; + out3 = (SpicePointFix *)end; + end += sizeof(SpicePointFix); + + out3->x = consume_int32(&in); + out3->y = consume_int32(&in); + } + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + return end; +} + +static uint8_t * parse_array_int32(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + uint32_t i; + + end = struct_data; + for (i = 0; i < this_ptr_info->nelements; i++) { + *(SPICE_FIXED28_4 *)end = consume_int32(&in); + end += sizeof(SPICE_FIXED28_4); + } + return end; +} + +static uint8_t * parse_msg_display_draw_stroke(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawStroke *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_path__extra_size; + size_t data_attr__extra_size; + size_t data_brush__extra_size; + { /* path */ + uint64_t path__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + path__value = read_uint64(pos); + ptr_size = validate_SpicePath(message_start, message_end, path__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_path__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* attr */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8); + size_t data_attr_style__extra_size; + uint32_t data_attr_style__array__nelements; + { /* style */ + uint64_t style__value; + uint32_t data_attr_style__array__nw_size; + uint32_t data_attr_style__array__mem_size; + uint8_t style_nseg__value; + pos = (start3 + 12); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + style__value = read_uint64(pos); + if (SPICE_UNLIKELY(message_start + style__value >= message_end)) { + goto error; + } + pos = start3 + 3; + if (SPICE_UNLIKELY(pos + 1 > message_end)) { + goto error; + } + style_nseg__value = read_uint8(pos); + data_attr_style__array__nelements = style_nseg__value; + + data_attr_style__array__nw_size = (4) * data_attr_style__array__nelements; + data_attr_style__array__mem_size = sizeof(SPICE_FIXED28_4) * data_attr_style__array__nelements; + if (SPICE_UNLIKELY(message_start + style__value + data_attr_style__array__nw_size > message_end)) { + goto error; + } + data_attr_style__extra_size = data_attr_style__array__mem_size + /* for alignment */ 3; + } + + data_attr__extra_size = data_attr_style__extra_size; + } + + { /* brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 28); + size_t data_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_brush_u__extra_size = data_brush_u_pat__extra_size; + } else { + data_brush_u__extra_size = 0; + } + + } + + data_brush__extra_size = data_brush_u__extra_size; + } + + data__extra_size = data_path__extra_size + data_attr__extra_size + data_brush__extra_size; + } + + nw_size = 80; + mem_size = sizeof(SpiceMsgDisplayDrawStroke) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawStroke); + in = start; + + out = (SpiceMsgDisplayDrawStroke *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpicePath; + ptr_info[n_ptr].dest = (void **)&out->data.path; + n_ptr++; + /* attr */ { + uint32_t style__array__nelements; + out->data.attr.flags = consume_uint8(&in); + consume_uint8(&in); + consume_uint8(&in); + out->data.attr.style_nseg = consume_uint8(&in); + consume_int32(&in); + consume_int32(&in); + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_array_int32; + ptr_info[n_ptr].dest = (void **)&out->data.attr.style; + style__array__nelements = out->data.attr.style_nseg; + ptr_info[n_ptr].nelements = style__array__nelements; + n_ptr++; + } + /* brush */ { + uint8_t *in_save; + out->data.brush.type = consume_uint32(&in); + in_save = in; + if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.brush.u.color = consume_uint32(&in); + } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.brush.u.pattern.pos.x = consume_int32(&in); + out->data.brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + out->data.fore_mode = consume_uint16(&in); + out->data.back_mode = consume_uint16(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static intptr_t validate_SpiceString(uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *start = message_start + offset; + SPICE_GNUC_UNUSED uint8_t *pos; + size_t mem_size, nw_size; + size_t u__nw_size, u__extra_size; + uint16_t flags__value; + uint32_t i; + + if (offset == 0) { + return 0; + } + + if (SPICE_UNLIKELY(start >= message_end)) { + goto error; + } + + { /* u */ + uint32_t u__mem_size; + uint32_t u__nelements; + pos = start + 2; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + flags__value = read_uint16(pos); + if ((flags__value & SPICE_STRING_FLAGS_RASTER_A1)) { + uint16_t length__value; + uint8_t *start2 = (start + 4); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = ((width__value + 7) / 8 ) * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A4)) { + uint16_t length__value; + uint8_t *start2 = (start + 4); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = ((4 * width__value + 7) / 8 ) * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A8)) { + uint16_t length__value; + uint8_t *start2 = (start + 4); + uint32_t u__element__nw_size; + uint32_t u__element__mem_size; + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + length__value = read_uint16(pos); + u__nelements = length__value; + + u__nw_size = 0; + u__mem_size = 0; + for (i = 0; i < u__nelements; i++) { + SPICE_GNUC_UNUSED uint8_t *start3 = start2; + size_t u__element_data__nw_size, u__element_data__mem_size; + uint32_t u__element_data__nelements; + { /* data */ + uint16_t width__value; + uint16_t height__value; + pos = start3 + 16; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + width__value = read_uint16(pos); + pos = start3 + 18; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + height__value = read_uint16(pos); + u__element_data__nelements = width__value * height__value; + + u__element_data__nw_size = u__element_data__nelements; + u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements; + } + + u__element__nw_size = 20 + u__element_data__nw_size; + u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size; + u__nw_size += u__element__nw_size; + u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4); + start2 += u__element__nw_size; + } + u__extra_size = u__mem_size; + } else { + u__nw_size = 0; + u__extra_size = 0; + } + + } + + nw_size = 4 + u__nw_size; + mem_size = sizeof(SpiceString) + u__extra_size; + + /* Check if struct fits in reported side */ + if (SPICE_UNLIKELY(start + nw_size > message_end)) { + goto error; + } + return mem_size; + + error: + return -1; +} + +static uint8_t * parse_struct_SpiceString(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor) +{ + uint8_t *in = message_start + this_ptr_info->offset; + uint8_t *end; + SpiceString *out; + uint32_t i; + + end = struct_data + sizeof(SpiceString); + out = (SpiceString *)struct_data; + + out->length = consume_uint16(&in); + out->flags = consume_uint16(&in); + if ((out->flags & SPICE_STRING_FLAGS_RASTER_A1)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = ((out2->width + 7) / 8 ) * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A4)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = ((4 * out2->width + 7) / 8 ) * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A8)) { + uint32_t glyphs__nelements; + void * *ptr_array; + int ptr_array_index; + glyphs__nelements = out->length; + ptr_array_index = 0; + ptr_array = (void **)out->glyphs; + end += sizeof(void *) * glyphs__nelements; + for (i = 0; i < glyphs__nelements; i++) { + SpiceRasterGlyph *out2; + uint32_t data__nelements; + ptr_array[ptr_array_index++] = end; + out2 = (SpiceRasterGlyph *)end; + end += sizeof(SpiceRasterGlyph); + + /* render_pos */ { + out2->render_pos.x = consume_int32(&in); + out2->render_pos.y = consume_int32(&in); + } + /* glyph_origin */ { + out2->glyph_origin.x = consume_int32(&in); + out2->glyph_origin.y = consume_int32(&in); + } + out2->width = consume_uint16(&in); + out2->height = consume_uint16(&in); + data__nelements = out2->width * out2->height; + memcpy(out2->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + /* Align ptr_array element to 4 bytes */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + } + } + return end; +} + +static uint8_t * parse_msg_display_draw_text(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[4]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawText *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_str__extra_size; + size_t data_fore_brush__extra_size; + size_t data_back_brush__extra_size; + { /* str */ + uint64_t str__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + str__value = read_uint64(pos); + ptr_size = validate_SpiceString(message_start, message_end, str__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_str__extra_size = ptr_size + /* for alignment */ 3; + } + + { /* fore_brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 24); + size_t data_fore_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_fore_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_fore_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_fore_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_fore_brush_u__extra_size = data_fore_brush_u_pat__extra_size; + } else { + data_fore_brush_u__extra_size = 0; + } + + } + + data_fore_brush__extra_size = data_fore_brush_u__extra_size; + } + + { /* back_brush */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 44); + size_t data_back_brush_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_BRUSH_TYPE_SOLID) { + data_back_brush_u__extra_size = 0; + } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) { + SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 4); + size_t data_back_brush_u_pat__extra_size; + { /* pat */ + uint64_t pat__value; + pos = (start4 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + pat__value = read_uint64(pos); + if (SPICE_UNLIKELY(pat__value == 0)) { + goto error; + } + ptr_size = validate_SpiceImage(message_start, message_end, pat__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_back_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3; + } + + data_back_brush_u__extra_size = data_back_brush_u_pat__extra_size; + } else { + data_back_brush_u__extra_size = 0; + } + + } + + data_back_brush__extra_size = data_back_brush_u__extra_size; + } + + data__extra_size = data_str__extra_size + data_fore_brush__extra_size + data_back_brush__extra_size; + } + + nw_size = 96; + mem_size = sizeof(SpiceMsgDisplayDrawText) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawText); + in = start; + + out = (SpiceMsgDisplayDrawText *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceString; + ptr_info[n_ptr].dest = (void **)&out->data.str; + n_ptr++; + /* back_area */ { + out->data.back_area.top = consume_int32(&in); + out->data.back_area.left = consume_int32(&in); + out->data.back_area.bottom = consume_int32(&in); + out->data.back_area.right = consume_int32(&in); + } + /* fore_brush */ { + uint8_t *in_save; + out->data.fore_brush.type = consume_uint32(&in); + in_save = in; + if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.fore_brush.u.color = consume_uint32(&in); + } else if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.fore_brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.fore_brush.u.pattern.pos.x = consume_int32(&in); + out->data.fore_brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + /* back_brush */ { + uint8_t *in_save; + out->data.back_brush.type = consume_uint32(&in); + in_save = in; + if (out->data.back_brush.type == SPICE_BRUSH_TYPE_SOLID) { + out->data.back_brush.u.color = consume_uint32(&in); + } else if (out->data.back_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.back_brush.u.pattern.pat; + n_ptr++; + /* pos */ { + out->data.back_brush.u.pattern.pos.x = consume_int32(&in); + out->data.back_brush.u.pattern.pos.y = consume_int32(&in); + } + } + in = in_save + 16; + } + out->data.fore_mode = consume_uint16(&in); + out->data.back_mode = consume_uint16(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_transparent(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawTransparent *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 0); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data__extra_size = data_src_bitmap__extra_size; + } + + nw_size = 60; + mem_size = sizeof(SpiceMsgDisplayDrawTransparent) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawTransparent); + in = start; + + out = (SpiceMsgDisplayDrawTransparent *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + out->data.src_color = consume_uint32(&in); + out->data.true_color = consume_uint32(&in); + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_display_draw_alpha_blend(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t base__extra_size; + size_t data__extra_size; + SpiceMsgDisplayDrawAlphaBlend *out; + uint32_t i; + + { /* base */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0); + size_t base_clip__extra_size; + { /* clip */ + SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 16); + size_t base_clip_u__extra_size; + uint32_t type__value; + { /* u */ + pos = start3 + 0; + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + type__value = read_uint32(pos); + if (type__value == SPICE_CLIP_TYPE_RECTS) { + uint64_t base_clip_u_rects__value; + pos = (start3 + 4); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + base_clip_u_rects__value = read_uint64(pos); + ptr_size = validate_SpiceClipRects(message_start, message_end, base_clip_u_rects__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + base_clip_u__extra_size = ptr_size + /* for alignment */ 3; + } else if (1) { + base_clip_u__extra_size = 0; + } else { + base_clip_u__extra_size = 0; + } + + } + + base_clip__extra_size = base_clip_u__extra_size; + } + + base__extra_size = base_clip__extra_size; + } + + { /* data */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 28); + size_t data_src_bitmap__extra_size; + { /* src_bitmap */ + uint64_t src_bitmap__value; + pos = (start2 + 1); + if (SPICE_UNLIKELY(pos + 8 > message_end)) { + goto error; + } + src_bitmap__value = read_uint64(pos); + ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value, minor); + if (SPICE_UNLIKELY(ptr_size < 0)) { + goto error; + } + data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3; + } + + data__extra_size = data_src_bitmap__extra_size; + } + + nw_size = 53; + mem_size = sizeof(SpiceMsgDisplayDrawAlphaBlend) + base__extra_size + data__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayDrawAlphaBlend); + in = start; + + out = (SpiceMsgDisplayDrawAlphaBlend *)data; + + /* base */ { + out->base.surface_id = 0; + /* box */ { + out->base.box.top = consume_int32(&in); + out->base.box.left = consume_int32(&in); + out->base.box.bottom = consume_int32(&in); + out->base.box.right = consume_int32(&in); + } + /* clip */ { + out->base.clip.type = consume_uint32(&in); + if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceClipRects; + ptr_info[n_ptr].dest = (void **)&out->base.clip.rects; + n_ptr++; + } else if (1) { + consume_uint64(&in); + } + } + } + /* data */ { + out->data.alpha_flags = 0; + out->data.alpha = consume_uint8(&in); + ptr_info[n_ptr].offset = consume_uint64(&in); + ptr_info[n_ptr].parse = parse_struct_SpiceImage; + ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap; + n_ptr++; + /* src_area */ { + out->data.src_area.top = consume_int32(&in); + out->data.src_area.left = consume_int32(&in); + out->data.src_area.bottom = consume_int32(&in); + out->data.src_area.right = consume_int32(&in); + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_DisplayChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[8] = { + parse_msg_display_mode, + parse_SpiceMsgEmpty, + parse_SpiceMsgEmpty, + parse_msg_display_copy_bits, + parse_msg_display_inval_list, + parse_msg_display_inval_all_pixmaps, + parse_msg_display_inval_palette, + parse_SpiceMsgEmpty + }; + static parse_msg_func_t funcs3[5] = { + parse_msg_display_stream_create, + parse_msg_display_stream_data, + parse_msg_display_stream_clip, + parse_msg_display_stream_destroy, + parse_SpiceMsgEmpty + }; + static parse_msg_func_t funcs4[12] = { + parse_msg_display_draw_fill, + parse_msg_display_draw_opaque, + parse_msg_display_draw_copy, + parse_msg_display_draw_blend, + parse_msg_display_draw_blackness, + parse_msg_display_draw_whiteness, + parse_msg_display_draw_invers, + parse_msg_display_draw_rop3, + parse_msg_display_draw_stroke, + parse_msg_display_draw_text, + parse_msg_display_draw_transparent, + parse_msg_display_draw_alpha_blend + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 109) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 122 && message_type < 127) { + return funcs3[message_type-122](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 302 && message_type < 314) { + return funcs4[message_type-302](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_inputs_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgInputsInit *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgInputsInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgInputsInit); + in = start; + + out = (SpiceMsgInputsInit *)data; + + out->keyboard_modifiers = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_inputs_key_modifiers(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgInputsKeyModifiers *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgInputsKeyModifiers); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgInputsKeyModifiers); + in = start; + + out = (SpiceMsgInputsKeyModifiers *)data; + + out->modifiers = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_InputsChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[2] = { + parse_msg_inputs_init, + parse_msg_inputs_key_modifiers + }; + static parse_msg_func_t funcs3[1] = { + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 103) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 111 && message_type < 112) { + return funcs3[message_type-111](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_cursor_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t cursor__nw_size; + SpiceMsgCursorInit *out; + + { /* cursor */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 9); + size_t cursor_data__nw_size; + uint32_t cursor_data__nelements; + { /* data */ + cursor_data__nelements = message_end - (start2 + 22); + + cursor_data__nw_size = cursor_data__nelements; + } + + cursor__nw_size = 22 + cursor_data__nw_size; + } + + nw_size = 9 + cursor__nw_size; + mem_size = sizeof(SpiceMsgCursorInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorInit); + in = start; + + out = (SpiceMsgCursorInit *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + out->trail_length = consume_uint16(&in); + out->trail_frequency = consume_uint16(&in); + out->visible = consume_uint8(&in); + /* cursor */ { + uint32_t data__nelements; + out->cursor.flags = consume_uint32(&in); + /* header */ { + out->cursor.header.unique = consume_uint64(&in); + out->cursor.header.type = consume_uint16(&in); + out->cursor.header.width = consume_uint16(&in); + out->cursor.header.height = consume_uint16(&in); + out->cursor.header.hot_spot_x = consume_uint16(&in); + out->cursor.header.hot_spot_y = consume_uint16(&in); + } + data__nelements = (message_end - in) / (1); + /* use array as pointer */ + out->cursor.data = (uint8_t *)in; + out->cursor.data_size = data__nelements; + in += data__nelements; + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_set(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t cursor__nw_size; + SpiceMsgCursorSet *out; + + { /* cursor */ + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 5); + size_t cursor_data__nw_size; + uint32_t cursor_data__nelements; + { /* data */ + cursor_data__nelements = message_end - (start2 + 22); + + cursor_data__nw_size = cursor_data__nelements; + } + + cursor__nw_size = 22 + cursor_data__nw_size; + } + + nw_size = 5 + cursor__nw_size; + mem_size = sizeof(SpiceMsgCursorSet); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorSet); + in = start; + + out = (SpiceMsgCursorSet *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + out->visible = consume_uint8(&in); + /* cursor */ { + uint32_t data__nelements; + out->cursor.flags = consume_uint32(&in); + /* header */ { + out->cursor.header.unique = consume_uint64(&in); + out->cursor.header.type = consume_uint16(&in); + out->cursor.header.width = consume_uint16(&in); + out->cursor.header.height = consume_uint16(&in); + out->cursor.header.hot_spot_x = consume_uint16(&in); + out->cursor.header.hot_spot_y = consume_uint16(&in); + } + data__nelements = (message_end - in) / (1); + /* use array as pointer */ + out->cursor.data = (uint8_t *)in; + out->cursor.data_size = data__nelements; + in += data__nelements; + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_move(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgCursorMove *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgCursorMove); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorMove); + in = start; + + out = (SpiceMsgCursorMove *)data; + + /* position */ { + out->position.x = consume_int16(&in); + out->position.y = consume_int16(&in); + } + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_trail(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgCursorTrail *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgCursorTrail); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgCursorTrail); + in = start; + + out = (SpiceMsgCursorTrail *)data; + + out->length = consume_uint16(&in); + out->frequency = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_cursor_inval_one(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisplayInvalOne *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgDisplayInvalOne); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisplayInvalOne); + in = start; + + out = (SpiceMsgDisplayInvalOne *)data; + + out->id = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_CursorChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[8] = { + parse_msg_cursor_init, + parse_SpiceMsgEmpty, + parse_msg_cursor_set, + parse_msg_cursor_move, + parse_SpiceMsgEmpty, + parse_msg_cursor_trail, + parse_msg_cursor_inval_one, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 109) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_playback_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPlaybackPacket *out; + + { /* data */ + data__nelements = message_end - (start + 4); + + data__nw_size = data__nelements; + } + + nw_size = 4 + data__nw_size; + mem_size = sizeof(SpiceMsgPlaybackPacket); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackPacket); + in = start; + + out = (SpiceMsgPlaybackPacket *)data; + + out->time = consume_uint32(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_playback_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgPlaybackMode *out; + + { /* data */ + data__nelements = message_end - (start + 8); + + data__nw_size = data__nelements; + } + + nw_size = 8 + data__nw_size; + mem_size = sizeof(SpiceMsgPlaybackMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackMode); + in = start; + + out = (SpiceMsgPlaybackMode *)data; + + out->time = consume_uint32(&in); + out->mode = consume_uint32(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msg_playback_start(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgPlaybackStart *out; + + nw_size = 16; + mem_size = sizeof(SpiceMsgPlaybackStart); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPlaybackStart); + in = start; + + out = (SpiceMsgPlaybackStart *)data; + + out->channels = consume_uint32(&in); + out->format = consume_uint32(&in); + out->frequency = consume_uint32(&in); + out->time = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_PlaybackChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[4] = { + parse_msg_playback_data, + parse_msg_playback_mode, + parse_msg_playback_start, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 105) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msg_record_start(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgRecordStart *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgRecordStart); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgRecordStart); + in = start; + + out = (SpiceMsgRecordStart *)data; + + out->channels = consume_uint32(&in); + out->format = consume_uint32(&in); + out->frequency = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_RecordChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[7] = { + parse_msg_migrate, + parse_SpiceMsgData, + parse_msg_set_ack, + parse_msg_ping, + parse_msg_wait_for_channels, + parse_msg_disconnecting, + parse_msg_notify + }; + static parse_msg_func_t funcs2[2] = { + parse_msg_record_start, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 8) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 103) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + +spice_parse_channel_func_t spice_get_server_channel_parser1(uint32_t channel, unsigned int *max_message_type) +{ + static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[7] = { + { NULL, 0 }, + { parse_MainChannel_msg, 111}, + { parse_DisplayChannel_msg, 313}, + { parse_InputsChannel_msg, 111}, + { parse_CursorChannel_msg, 108}, + { parse_PlaybackChannel_msg, 104}, + { parse_RecordChannel_msg, 102} + }; + if (channel < 7) { + if (max_message_type != NULL) { + *max_message_type = channels[channel].max_messages; + } + return channels[channel].func; + } + return NULL; +} + +uint8_t * spice_parse_msg1(uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + spice_parse_channel_func_t func; + func = spice_get_server_channel_parser1(channel, NULL); + if (func != NULL) { + return func(message_start, message_end, message_type, minor, size_out, free_message); + } + return NULL; +} diff --git a/spice-common/common/generated_client_marshallers.c b/spice-common/common/generated_client_marshallers.c new file mode 100644 index 0000000..861d96c --- /dev/null +++ b/spice-common/common/generated_client_marshallers.c @@ -0,0 +1,494 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/marshaller.h" + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#pragma warning(disable:4018) +#endif + +static void spice_marshall_msgc_ack_sync(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcAckSync *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcAckSync *src; + src = (SpiceMsgcAckSync *)msg; + + spice_marshaller_add_uint32(m, src->generation); +} + +static void spice_marshall_SpiceMsgEmpty(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgEmpty *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_pong(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPing *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPing *src; + src = (SpiceMsgPing *)msg; + + spice_marshaller_add_uint32(m, src->id); + spice_marshaller_add_uint64(m, src->timestamp); +} + +static void spice_marshall_SpiceMsgData(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_disconnecting(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisconnect *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisconnect *src; + src = (SpiceMsgDisconnect *)msg; + + spice_marshaller_add_uint64(m, src->time_stamp); + spice_marshaller_add_uint32(m, src->reason); +} + +static void spice_marshall_msgc_main_client_info(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcClientInfo *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcClientInfo *src; + src = (SpiceMsgcClientInfo *)msg; + + spice_marshaller_add_uint64(m, src->cache_size); +} + +static void spice_marshall_msgc_main_mouse_mode_request(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainMouseModeRequest *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainMouseModeRequest *src; + src = (SpiceMsgcMainMouseModeRequest *)msg; + + spice_marshaller_add_uint16(m, src->mode); +} + +static void spice_marshall_msgc_main_agent_start(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainAgentStart *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainAgentStart *src; + src = (SpiceMsgcMainAgentStart *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +static void spice_marshall_msgc_main_agent_token(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainAgentTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainAgentTokens *src; + src = (SpiceMsgcMainAgentTokens *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +static void spice_marshall_msgc_main_migrate_dst_do_seamless(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainMigrateDstDoSeamless *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainMigrateDstDoSeamless *src; + src = (SpiceMsgcMainMigrateDstDoSeamless *)msg; + + spice_marshaller_add_uint32(m, src->src_version); +} + +static void spice_marshall_msgc_display_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcDisplayInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcDisplayInit *src; + src = (SpiceMsgcDisplayInit *)msg; + + spice_marshaller_add_uint8(m, src->pixmap_cache_id); + spice_marshaller_add_int64(m, src->pixmap_cache_size); + spice_marshaller_add_uint8(m, src->glz_dictionary_id); + spice_marshaller_add_int32(m, src->glz_dictionary_window_size); +} + +static void spice_marshall_msgc_display_stream_report(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcDisplayStreamReport *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcDisplayStreamReport *src; + src = (SpiceMsgcDisplayStreamReport *)msg; + + spice_marshaller_add_uint32(m, src->stream_id); + spice_marshaller_add_uint32(m, src->unique_id); + spice_marshaller_add_uint32(m, src->start_frame_mm_time); + spice_marshaller_add_uint32(m, src->end_frame_mm_time); + spice_marshaller_add_uint32(m, src->num_frames); + spice_marshaller_add_uint32(m, src->num_drops); + spice_marshaller_add_int32(m, src->last_frame_delay); + spice_marshaller_add_uint32(m, src->audio_delay); +} + +static void spice_marshall_msgc_display_preferred_compression(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcDisplayPreferredCompression *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcDisplayPreferredCompression *src; + src = (SpiceMsgcDisplayPreferredCompression *)msg; + + spice_marshaller_add_uint8(m, src->image_compression); +} + +static void spice_marshall_msgc_display_gl_draw_done(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcDisplayGlDrawDone *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_inputs_key_down(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyDown *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyDown *src; + src = (SpiceMsgcKeyDown *)msg; + + spice_marshaller_add_uint32(m, src->code); +} + +static void spice_marshall_msgc_inputs_key_up(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyUp *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyUp *src; + src = (SpiceMsgcKeyUp *)msg; + + spice_marshaller_add_uint32(m, src->code); +} + +static void spice_marshall_msgc_inputs_key_modifiers(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyModifiers *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyModifiers *src; + src = (SpiceMsgcKeyModifiers *)msg; + + spice_marshaller_add_uint16(m, src->modifiers); +} + +static void spice_marshall_msgc_inputs_mouse_motion(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMouseMotion *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMouseMotion *src; + src = (SpiceMsgcMouseMotion *)msg; + + spice_marshaller_add_int32(m, src->dx); + spice_marshaller_add_int32(m, src->dy); + spice_marshaller_add_uint16(m, src->buttons_state); +} + +static void spice_marshall_msgc_inputs_mouse_position(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMousePosition *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMousePosition *src; + src = (SpiceMsgcMousePosition *)msg; + + spice_marshaller_add_uint32(m, src->x); + spice_marshaller_add_uint32(m, src->y); + spice_marshaller_add_uint16(m, src->buttons_state); + spice_marshaller_add_uint8(m, src->display_id); +} + +static void spice_marshall_msgc_inputs_mouse_press(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMousePress *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMousePress *src; + src = (SpiceMsgcMousePress *)msg; + + spice_marshaller_add_uint8(m, src->button); + spice_marshaller_add_uint16(m, src->buttons_state); +} + +static void spice_marshall_msgc_inputs_mouse_release(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMouseRelease *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMouseRelease *src; + src = (SpiceMsgcMouseRelease *)msg; + + spice_marshaller_add_uint8(m, src->button); + spice_marshaller_add_uint16(m, src->buttons_state); +} + +static void spice_marshall_msgc_record_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordPacket *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordPacket *src; + src = (SpiceMsgcRecordPacket *)msg; + + spice_marshaller_add_uint32(m, src->time); + /* Don't marshall @nomarshal data */ +} + +static void spice_marshall_msgc_record_mode(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordMode *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordMode *src; + src = (SpiceMsgcRecordMode *)msg; + + spice_marshaller_add_uint32(m, src->time); + spice_marshaller_add_uint16(m, src->mode); + /* Remaining data must be appended manually */ +} + +static void spice_marshall_msgc_record_start_mark(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordStartMark *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordStartMark *src; + src = (SpiceMsgcRecordStartMark *)msg; + + spice_marshaller_add_uint32(m, src->time); +} + +SPICE_GNUC_UNUSED static void spice_marshall_array_uint8(SpiceMarshaller *m, uint8_t *ptr, unsigned count) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + uint32_t i; + + for (i = 0; i < count; i++) { + spice_marshaller_add_uint8(m, *ptr++); + } +} + +static void spice_marshall_msgc_tunnel_service_add(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelAddGenericService *msg, SpiceMarshaller **name_out, SpiceMarshaller **description_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelAddGenericService *src; + uint32_t i; + *name_out = NULL; + *description_out = NULL; + src = (SpiceMsgcTunnelAddGenericService *)msg; + + spice_marshaller_add_uint16(m, src->type); + spice_marshaller_add_uint32(m, src->id); + spice_marshaller_add_uint32(m, src->group); + spice_marshaller_add_uint32(m, src->port); + *name_out = spice_marshaller_get_ptr_submarshaller(m, 0); + *description_out = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->type == SPICE_TUNNEL_SERVICE_TYPE_IPP) { + uint8_t *ipv4__element; + spice_marshaller_add_uint16(m, src->u.ip.type); + if (src->u.ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) { + ipv4__element = src->u.ip.u.ipv4; + for (i = 0; i < 4; i++) { + spice_marshaller_add_uint8(m, *ipv4__element); + ipv4__element++; + } + } + } +} + +static void spice_marshall_msgc_tunnel_service_remove(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelRemoveService *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelRemoveService *src; + src = (SpiceMsgcTunnelRemoveService *)msg; + + spice_marshaller_add_uint32(m, src->id); +} + +static void spice_marshall_msgc_tunnel_socket_open_ack(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketOpenAck *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketOpenAck *src; + src = (SpiceMsgcTunnelSocketOpenAck *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + spice_marshaller_add_uint32(m, src->tokens); +} + +static void spice_marshall_msgc_tunnel_socket_open_nack(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketOpenNack *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketOpenNack *src; + src = (SpiceMsgcTunnelSocketOpenNack *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +static void spice_marshall_msgc_tunnel_socket_fin(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketFin *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketFin *src; + src = (SpiceMsgcTunnelSocketFin *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +static void spice_marshall_msgc_tunnel_socket_closed(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketClosed *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketClosed *src; + src = (SpiceMsgcTunnelSocketClosed *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +static void spice_marshall_msgc_tunnel_socket_closed_ack(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketClosedAck *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketClosedAck *src; + src = (SpiceMsgcTunnelSocketClosedAck *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +static void spice_marshall_msgc_tunnel_socket_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketData *src; + src = (SpiceMsgcTunnelSocketData *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + /* Remaining data must be appended manually */ +} + +static void spice_marshall_msgc_tunnel_socket_token(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcTunnelSocketTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcTunnelSocketTokens *src; + src = (SpiceMsgcTunnelSocketTokens *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + spice_marshaller_add_uint32(m, src->num_tokens); +} + +#ifdef USE_SMARTCARD +static void spice_marshall_msgc_smartcard_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcSmartcard *msg, SpiceMarshaller **reader_name_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcSmartcard *src; + *reader_name_out = NULL; + src = (SpiceMsgcSmartcard *)msg; + + /* header */ { + spice_marshaller_add_uint32(m, src->header.type); + spice_marshaller_add_uint32(m, src->header.reader_id); + spice_marshaller_add_uint32(m, src->header.length); + } + if (src->header.type == SPICE_VSC_MESSAGE_TYPE_ReaderAdd) { + /* Don't marshall @nomarshal reader_name */ + } else if (src->header.type == SPICE_VSC_MESSAGE_TYPE_ATR || src->header.type == SPICE_VSC_MESSAGE_TYPE_APDU) { + /* Remaining data must be appended manually */ + } else if (src->header.type == SPICE_VSC_MESSAGE_TYPE_Error) { + spice_marshaller_add_uint32(m, src->error.code); + } +} + +static void spice_marshall_msgc_smartcard_header(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED VSCMsgHeader *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + VSCMsgHeader *src; + src = (VSCMsgHeader *)msg; + + spice_marshaller_add_uint32(m, src->type); + spice_marshaller_add_uint32(m, src->reader_id); + spice_marshaller_add_uint32(m, src->length); +} + +static void spice_marshall_msgc_smartcard_error(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED VSCMsgError *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + VSCMsgError *src; + src = (VSCMsgError *)msg; + + spice_marshaller_add_uint32(m, src->code); +} + +static void spice_marshall_msgc_smartcard_atr(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED VSCMsgATR *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_smartcard_reader_add(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED VSCMsgReaderAdd *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +#endif /* USE_SMARTCARD */ +static void spice_marshall_msgc_port_event(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcPortEvent *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcPortEvent *src; + src = (SpiceMsgcPortEvent *)msg; + + spice_marshaller_add_uint8(m, src->event); +} + +SpiceMessageMarshallers * spice_message_marshallers_get(void) +{ + static SpiceMessageMarshallers marshallers = {NULL}; + + marshallers.msg_SpiceMsgData = spice_marshall_SpiceMsgData; + marshallers.msg_SpiceMsgEmpty = spice_marshall_SpiceMsgEmpty; + marshallers.msgc_ack_sync = spice_marshall_msgc_ack_sync; + marshallers.msgc_disconnecting = spice_marshall_msgc_disconnecting; + marshallers.msgc_display_gl_draw_done = spice_marshall_msgc_display_gl_draw_done; + marshallers.msgc_display_init = spice_marshall_msgc_display_init; + marshallers.msgc_display_preferred_compression = spice_marshall_msgc_display_preferred_compression; + marshallers.msgc_display_stream_report = spice_marshall_msgc_display_stream_report; + marshallers.msgc_inputs_key_down = spice_marshall_msgc_inputs_key_down; + marshallers.msgc_inputs_key_modifiers = spice_marshall_msgc_inputs_key_modifiers; + marshallers.msgc_inputs_key_up = spice_marshall_msgc_inputs_key_up; + marshallers.msgc_inputs_mouse_motion = spice_marshall_msgc_inputs_mouse_motion; + marshallers.msgc_inputs_mouse_position = spice_marshall_msgc_inputs_mouse_position; + marshallers.msgc_inputs_mouse_press = spice_marshall_msgc_inputs_mouse_press; + marshallers.msgc_inputs_mouse_release = spice_marshall_msgc_inputs_mouse_release; + marshallers.msgc_main_agent_start = spice_marshall_msgc_main_agent_start; + marshallers.msgc_main_agent_token = spice_marshall_msgc_main_agent_token; + marshallers.msgc_main_client_info = spice_marshall_msgc_main_client_info; + marshallers.msgc_main_migrate_dst_do_seamless = spice_marshall_msgc_main_migrate_dst_do_seamless; + marshallers.msgc_main_mouse_mode_request = spice_marshall_msgc_main_mouse_mode_request; + marshallers.msgc_pong = spice_marshall_msgc_pong; + marshallers.msgc_port_event = spice_marshall_msgc_port_event; + marshallers.msgc_record_data = spice_marshall_msgc_record_data; + marshallers.msgc_record_mode = spice_marshall_msgc_record_mode; + marshallers.msgc_record_start_mark = spice_marshall_msgc_record_start_mark; +#ifdef USE_SMARTCARD + marshallers.msgc_smartcard_atr = spice_marshall_msgc_smartcard_atr; +#endif /* USE_SMARTCARD */ +#ifdef USE_SMARTCARD + marshallers.msgc_smartcard_data = spice_marshall_msgc_smartcard_data; +#endif /* USE_SMARTCARD */ +#ifdef USE_SMARTCARD + marshallers.msgc_smartcard_error = spice_marshall_msgc_smartcard_error; +#endif /* USE_SMARTCARD */ +#ifdef USE_SMARTCARD + marshallers.msgc_smartcard_header = spice_marshall_msgc_smartcard_header; +#endif /* USE_SMARTCARD */ +#ifdef USE_SMARTCARD + marshallers.msgc_smartcard_reader_add = spice_marshall_msgc_smartcard_reader_add; +#endif /* USE_SMARTCARD */ + marshallers.msgc_tunnel_service_add = spice_marshall_msgc_tunnel_service_add; + marshallers.msgc_tunnel_service_remove = spice_marshall_msgc_tunnel_service_remove; + marshallers.msgc_tunnel_socket_closed = spice_marshall_msgc_tunnel_socket_closed; + marshallers.msgc_tunnel_socket_closed_ack = spice_marshall_msgc_tunnel_socket_closed_ack; + marshallers.msgc_tunnel_socket_data = spice_marshall_msgc_tunnel_socket_data; + marshallers.msgc_tunnel_socket_fin = spice_marshall_msgc_tunnel_socket_fin; + marshallers.msgc_tunnel_socket_open_ack = spice_marshall_msgc_tunnel_socket_open_ack; + marshallers.msgc_tunnel_socket_open_nack = spice_marshall_msgc_tunnel_socket_open_nack; + marshallers.msgc_tunnel_socket_token = spice_marshall_msgc_tunnel_socket_token; + + return &marshallers; +} + diff --git a/spice-common/common/generated_client_marshallers1.c b/spice-common/common/generated_client_marshallers1.c new file mode 100644 index 0000000..5a0ea19 --- /dev/null +++ b/spice-common/common/generated_client_marshallers1.c @@ -0,0 +1,251 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/marshaller.h" + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#pragma warning(disable:4018) +#endif + +static void spice_marshall_msgc_ack_sync(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcAckSync *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcAckSync *src; + src = (SpiceMsgcAckSync *)msg; + + spice_marshaller_add_uint32(m, src->generation); +} + +static void spice_marshall_SpiceMsgEmpty(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgEmpty *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_pong(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPing *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPing *src; + src = (SpiceMsgPing *)msg; + + spice_marshaller_add_uint32(m, src->id); + spice_marshaller_add_uint64(m, src->timestamp); +} + +static void spice_marshall_SpiceMsgData(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +static void spice_marshall_msgc_disconnecting(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisconnect *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisconnect *src; + src = (SpiceMsgDisconnect *)msg; + + spice_marshaller_add_uint64(m, src->time_stamp); + spice_marshaller_add_uint32(m, src->reason); +} + +static void spice_marshall_msgc_main_client_info(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcClientInfo *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcClientInfo *src; + src = (SpiceMsgcClientInfo *)msg; + + spice_marshaller_add_uint64(m, src->cache_size); +} + +static void spice_marshall_msgc_main_mouse_mode_request(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainMouseModeRequest *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainMouseModeRequest *src; + src = (SpiceMsgcMainMouseModeRequest *)msg; + + spice_marshaller_add_uint32(m, src->mode); +} + +static void spice_marshall_msgc_main_agent_start(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainAgentStart *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainAgentStart *src; + src = (SpiceMsgcMainAgentStart *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +static void spice_marshall_msgc_main_agent_token(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMainAgentTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMainAgentTokens *src; + src = (SpiceMsgcMainAgentTokens *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +static void spice_marshall_msgc_display_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcDisplayInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcDisplayInit *src; + src = (SpiceMsgcDisplayInit *)msg; + + spice_marshaller_add_uint8(m, src->pixmap_cache_id); + spice_marshaller_add_int64(m, src->pixmap_cache_size); + spice_marshaller_add_uint8(m, src->glz_dictionary_id); + spice_marshaller_add_int32(m, src->glz_dictionary_window_size); +} + +static void spice_marshall_msgc_inputs_key_down(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyDown *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyDown *src; + src = (SpiceMsgcKeyDown *)msg; + + spice_marshaller_add_uint32(m, src->code); +} + +static void spice_marshall_msgc_inputs_key_up(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyUp *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyUp *src; + src = (SpiceMsgcKeyUp *)msg; + + spice_marshaller_add_uint32(m, src->code); +} + +static void spice_marshall_msgc_inputs_key_modifiers(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcKeyModifiers *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcKeyModifiers *src; + src = (SpiceMsgcKeyModifiers *)msg; + + spice_marshaller_add_uint32(m, src->modifiers); +} + +static void spice_marshall_msgc_inputs_mouse_motion(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMouseMotion *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMouseMotion *src; + src = (SpiceMsgcMouseMotion *)msg; + + spice_marshaller_add_int32(m, src->dx); + spice_marshaller_add_int32(m, src->dy); + spice_marshaller_add_uint32(m, src->buttons_state); +} + +static void spice_marshall_msgc_inputs_mouse_position(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMousePosition *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMousePosition *src; + src = (SpiceMsgcMousePosition *)msg; + + spice_marshaller_add_uint32(m, src->x); + spice_marshaller_add_uint32(m, src->y); + spice_marshaller_add_uint32(m, src->buttons_state); + spice_marshaller_add_uint8(m, src->display_id); +} + +static void spice_marshall_msgc_inputs_mouse_press(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMousePress *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMousePress *src; + src = (SpiceMsgcMousePress *)msg; + + spice_marshaller_add_uint32(m, src->button); + spice_marshaller_add_uint32(m, src->buttons_state); +} + +static void spice_marshall_msgc_inputs_mouse_release(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcMouseRelease *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcMouseRelease *src; + src = (SpiceMsgcMouseRelease *)msg; + + spice_marshaller_add_uint32(m, src->button); + spice_marshaller_add_uint32(m, src->buttons_state); +} + +static void spice_marshall_msgc_record_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordPacket *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordPacket *src; + src = (SpiceMsgcRecordPacket *)msg; + + spice_marshaller_add_uint32(m, src->time); + /* Don't marshall @nomarshal data */ +} + +static void spice_marshall_msgc_record_mode(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordMode *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordMode *src; + src = (SpiceMsgcRecordMode *)msg; + + spice_marshaller_add_uint32(m, src->time); + spice_marshaller_add_uint32(m, src->mode); + /* Remaining data must be appended manually */ +} + +static void spice_marshall_msgc_record_start_mark(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgcRecordStartMark *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgcRecordStartMark *src; + src = (SpiceMsgcRecordStartMark *)msg; + + spice_marshaller_add_uint32(m, src->time); +} + +SpiceMessageMarshallers * spice_message_marshallers_get1(void) +{ + static SpiceMessageMarshallers marshallers = {NULL}; + + marshallers.msg_SpiceMsgData = spice_marshall_SpiceMsgData; + marshallers.msg_SpiceMsgEmpty = spice_marshall_SpiceMsgEmpty; + marshallers.msgc_ack_sync = spice_marshall_msgc_ack_sync; + marshallers.msgc_disconnecting = spice_marshall_msgc_disconnecting; + marshallers.msgc_display_init = spice_marshall_msgc_display_init; + marshallers.msgc_inputs_key_down = spice_marshall_msgc_inputs_key_down; + marshallers.msgc_inputs_key_modifiers = spice_marshall_msgc_inputs_key_modifiers; + marshallers.msgc_inputs_key_up = spice_marshall_msgc_inputs_key_up; + marshallers.msgc_inputs_mouse_motion = spice_marshall_msgc_inputs_mouse_motion; + marshallers.msgc_inputs_mouse_position = spice_marshall_msgc_inputs_mouse_position; + marshallers.msgc_inputs_mouse_press = spice_marshall_msgc_inputs_mouse_press; + marshallers.msgc_inputs_mouse_release = spice_marshall_msgc_inputs_mouse_release; + marshallers.msgc_main_agent_start = spice_marshall_msgc_main_agent_start; + marshallers.msgc_main_agent_token = spice_marshall_msgc_main_agent_token; + marshallers.msgc_main_client_info = spice_marshall_msgc_main_client_info; + marshallers.msgc_main_mouse_mode_request = spice_marshall_msgc_main_mouse_mode_request; + marshallers.msgc_pong = spice_marshall_msgc_pong; + marshallers.msgc_record_data = spice_marshall_msgc_record_data; + marshallers.msgc_record_mode = spice_marshall_msgc_record_mode; + marshallers.msgc_record_start_mark = spice_marshall_msgc_record_start_mark; + + return &marshallers; +} + diff --git a/spice-common/common/generated_server_demarshallers.c b/spice-common/common/generated_server_demarshallers.c new file mode 100644 index 0000000..9d1dfca --- /dev/null +++ b/spice-common/common/generated_server_demarshallers.c @@ -0,0 +1,2176 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#endif + + + +#ifdef WORDS_BIGENDIAN +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) *(int8_t *)(ptr) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) *(uint8_t *)(ptr) = val +#define read_int16(ptr) ((int16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_int16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_uint16(ptr) ((uint16_t)SPICE_BYTESWAP16(*((uint16_t *)(ptr)))) +#define write_uint16(ptr, val) *(uint16_t *)(ptr) = SPICE_BYTESWAP16((uint16_t)val) +#define read_int32(ptr) ((int32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_int32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr)))) +#define write_uint32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val) +#define read_int64(ptr) ((int64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_int64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#define read_uint64(ptr) ((uint64_t)SPICE_BYTESWAP64(*((uint64_t *)(ptr)))) +#define write_uint64(ptr, val) *(uint64_t *)(ptr) = SPICE_BYTESWAP64((uint64_t)val) +#else +#define read_int8(ptr) (*((int8_t *)(ptr))) +#define write_int8(ptr, val) (*((int8_t *)(ptr))) = val +#define read_uint8(ptr) (*((uint8_t *)(ptr))) +#define write_uint8(ptr, val) (*((uint8_t *)(ptr))) = val +#define read_int16(ptr) (*((int16_t *)(ptr))) +#define write_int16(ptr, val) (*((int16_t *)(ptr))) = val +#define read_uint16(ptr) (*((uint16_t *)(ptr))) +#define write_uint16(ptr, val) (*((uint16_t *)(ptr))) = val +#define read_int32(ptr) (*((int32_t *)(ptr))) +#define write_int32(ptr, val) (*((int32_t *)(ptr))) = val +#define read_uint32(ptr) (*((uint32_t *)(ptr))) +#define write_uint32(ptr, val) (*((uint32_t *)(ptr))) = val +#define read_int64(ptr) (*((int64_t *)(ptr))) +#define write_int64(ptr, val) (*((int64_t *)(ptr))) = val +#define read_uint64(ptr) (*((uint64_t *)(ptr))) +#define write_uint64(ptr, val) (*((uint64_t *)(ptr))) = val +#endif + +static int8_t SPICE_GNUC_UNUSED consume_int8(uint8_t **ptr) +{ + int8_t val; + val = read_int8(*ptr); + *ptr += 1; + return val; +} + +static uint8_t SPICE_GNUC_UNUSED consume_uint8(uint8_t **ptr) +{ + uint8_t val; + val = read_uint8(*ptr); + *ptr += 1; + return val; +} + +static int16_t SPICE_GNUC_UNUSED consume_int16(uint8_t **ptr) +{ + int16_t val; + val = read_int16(*ptr); + *ptr += 2; + return val; +} + +static uint16_t SPICE_GNUC_UNUSED consume_uint16(uint8_t **ptr) +{ + uint16_t val; + val = read_uint16(*ptr); + *ptr += 2; + return val; +} + +static int32_t SPICE_GNUC_UNUSED consume_int32(uint8_t **ptr) +{ + int32_t val; + val = read_int32(*ptr); + *ptr += 4; + return val; +} + +static uint32_t SPICE_GNUC_UNUSED consume_uint32(uint8_t **ptr) +{ + uint32_t val; + val = read_uint32(*ptr); + *ptr += 4; + return val; +} + +static int64_t SPICE_GNUC_UNUSED consume_int64(uint8_t **ptr) +{ + int64_t val; + val = read_int64(*ptr); + *ptr += 8; + return val; +} + +static uint64_t SPICE_GNUC_UNUSED consume_uint64(uint8_t **ptr) +{ + uint64_t val; + val = read_uint64(*ptr); + *ptr += 8; + return val; +} +static int SPICE_GNUC_UNUSED consume_fd(uint8_t **ptr) +{ + return -1; +} + +typedef struct PointerInfo PointerInfo; +typedef void (*message_destructor_t)(uint8_t *message); +typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor); +typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message); +typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message); + +struct PointerInfo { + uint64_t offset; + parse_func_t parse; + void * *dest; + uint32_t nelements; +}; + +static uint8_t * parse_msgc_ack_sync(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcAckSync *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcAckSync); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcAckSync); + in = start; + + out = (SpiceMsgcAckSync *)data; + + out->generation = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SpiceMsgEmpty(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + + nw_size = 0; + mem_size = sizeof(SpiceMsgEmpty); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgEmpty); + in = start; + + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_pong(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgPing *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgPing); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgPing); + in = start; + + out = (SpiceMsgPing *)data; + + out->id = consume_uint32(&in); + out->timestamp = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static void nofree(SPICE_GNUC_UNUSED uint8_t *data) +{ +} + +static uint8_t * parse_SpiceMsgData(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t data__nw_size; + uint32_t data__nelements; + + { /* data */ + data__nelements = message_end - (start + 0); + + data__nw_size = data__nelements; + } + + nw_size = 0 + data__nw_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = message_start; + *size = message_end - message_start; + *free_message = nofree; + return data; + +} + +static uint8_t * parse_msgc_disconnecting(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgDisconnect *out; + + nw_size = 12; + mem_size = sizeof(SpiceMsgDisconnect); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgDisconnect); + in = start; + + out = (SpiceMsgDisconnect *)data; + + out->time_stamp = consume_uint64(&in); + out->reason = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_main_client_info(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcClientInfo *out; + + nw_size = 8; + mem_size = sizeof(SpiceMsgcClientInfo); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcClientInfo); + in = start; + + out = (SpiceMsgcClientInfo *)data; + + out->cache_size = consume_uint64(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_main_mouse_mode_request(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMainMouseModeRequest *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcMainMouseModeRequest); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMainMouseModeRequest); + in = start; + + out = (SpiceMsgcMainMouseModeRequest *)data; + + out->mode = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_main_agent_start(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMainAgentStart *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcMainAgentStart); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMainAgentStart); + in = start; + + out = (SpiceMsgcMainAgentStart *)data; + + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_main_agent_token(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMainAgentTokens *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcMainAgentTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMainAgentTokens); + in = start; + + out = (SpiceMsgcMainAgentTokens *)data; + + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_main_migrate_dst_do_seamless(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMainMigrateDstDoSeamless *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcMainMigrateDstDoSeamless); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMainMigrateDstDoSeamless); + in = start; + + out = (SpiceMsgcMainMigrateDstDoSeamless *)data; + + out->src_version = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_MainChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[11] = { + parse_msgc_main_client_info, + parse_SpiceMsgEmpty, + parse_SpiceMsgEmpty, + parse_SpiceMsgEmpty, + parse_msgc_main_mouse_mode_request, + parse_msgc_main_agent_start, + parse_SpiceMsgData, + parse_msgc_main_agent_token, + parse_SpiceMsgEmpty, + parse_msgc_main_migrate_dst_do_seamless, + parse_SpiceMsgEmpty + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 112) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msgc_display_init(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcDisplayInit *out; + + nw_size = 14; + mem_size = sizeof(SpiceMsgcDisplayInit); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcDisplayInit); + in = start; + + out = (SpiceMsgcDisplayInit *)data; + + out->pixmap_cache_id = consume_uint8(&in); + out->pixmap_cache_size = consume_int64(&in); + out->glz_dictionary_id = consume_uint8(&in); + out->glz_dictionary_window_size = consume_int32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_display_stream_report(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcDisplayStreamReport *out; + + nw_size = 32; + mem_size = sizeof(SpiceMsgcDisplayStreamReport); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcDisplayStreamReport); + in = start; + + out = (SpiceMsgcDisplayStreamReport *)data; + + out->stream_id = consume_uint32(&in); + out->unique_id = consume_uint32(&in); + out->start_frame_mm_time = consume_uint32(&in); + out->end_frame_mm_time = consume_uint32(&in); + out->num_frames = consume_uint32(&in); + out->num_drops = consume_uint32(&in); + out->last_frame_delay = consume_int32(&in); + out->audio_delay = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_display_preferred_compression(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcDisplayPreferredCompression *out; + + nw_size = 1; + mem_size = sizeof(SpiceMsgcDisplayPreferredCompression); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcDisplayPreferredCompression); + in = start; + + out = (SpiceMsgcDisplayPreferredCompression *)data; + + out->image_compression = consume_uint8(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_display_gl_draw_done(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + + nw_size = 0; + mem_size = sizeof(SpiceMsgcDisplayGlDrawDone); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcDisplayGlDrawDone); + in = start; + + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_DisplayChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[4] = { + parse_msgc_display_init, + parse_msgc_display_stream_report, + parse_msgc_display_preferred_compression, + parse_msgc_display_gl_draw_done + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 105) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msgc_inputs_key_down(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcKeyDown *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcKeyDown); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcKeyDown); + in = start; + + out = (SpiceMsgcKeyDown *)data; + + out->code = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_key_up(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcKeyUp *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcKeyUp); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcKeyUp); + in = start; + + out = (SpiceMsgcKeyUp *)data; + + out->code = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_key_modifiers(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcKeyModifiers *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcKeyModifiers); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcKeyModifiers); + in = start; + + out = (SpiceMsgcKeyModifiers *)data; + + out->modifiers = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_mouse_motion(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMouseMotion *out; + + nw_size = 10; + mem_size = sizeof(SpiceMsgcMouseMotion); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMouseMotion); + in = start; + + out = (SpiceMsgcMouseMotion *)data; + + out->dx = consume_int32(&in); + out->dy = consume_int32(&in); + out->buttons_state = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_mouse_position(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMousePosition *out; + + nw_size = 11; + mem_size = sizeof(SpiceMsgcMousePosition); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMousePosition); + in = start; + + out = (SpiceMsgcMousePosition *)data; + + out->x = consume_uint32(&in); + out->y = consume_uint32(&in); + out->buttons_state = consume_uint16(&in); + out->display_id = consume_uint8(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_mouse_press(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMousePress *out; + + nw_size = 3; + mem_size = sizeof(SpiceMsgcMousePress); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMousePress); + in = start; + + out = (SpiceMsgcMousePress *)data; + + out->button = consume_uint8(&in); + out->buttons_state = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_inputs_mouse_release(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcMouseRelease *out; + + nw_size = 3; + mem_size = sizeof(SpiceMsgcMouseRelease); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcMouseRelease); + in = start; + + out = (SpiceMsgcMouseRelease *)data; + + out->button = consume_uint8(&in); + out->buttons_state = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_InputsChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[4] = { + parse_msgc_inputs_key_down, + parse_msgc_inputs_key_up, + parse_msgc_inputs_key_modifiers, + parse_SpiceMsgData + }; + static parse_msg_func_t funcs3[4] = { + parse_msgc_inputs_mouse_motion, + parse_msgc_inputs_mouse_position, + parse_msgc_inputs_mouse_press, + parse_msgc_inputs_mouse_release + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 105) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 111 && message_type < 115) { + return funcs3[message_type-111](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_CursorChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_PlaybackChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msgc_record_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgcRecordPacket *out; + + { /* data */ + data__nelements = message_end - (start + 4); + + data__nw_size = data__nelements; + } + + nw_size = 4 + data__nw_size; + mem_size = sizeof(SpiceMsgcRecordPacket); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcRecordPacket); + in = start; + + out = (SpiceMsgcRecordPacket *)data; + + out->time = consume_uint32(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_record_mode(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size; + uint32_t data__nelements; + SpiceMsgcRecordMode *out; + + { /* data */ + data__nelements = message_end - (start + 6); + + data__nw_size = data__nelements; + } + + nw_size = 6 + data__nw_size; + mem_size = sizeof(SpiceMsgcRecordMode); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcRecordMode); + in = start; + + out = (SpiceMsgcRecordMode *)data; + + out->time = consume_uint32(&in); + out->mode = consume_uint16(&in); + /* use array as pointer */ + out->data = (uint8_t *)in; + out->data_size = data__nelements; + in += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_record_start_mark(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcRecordStartMark *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcRecordStartMark); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcRecordStartMark); + in = start; + + out = (SpiceMsgcRecordStartMark *)data; + + out->time = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_RecordChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[3] = { + parse_msgc_record_data, + parse_msgc_record_mode, + parse_msgc_record_start_mark + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 104) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msgc_tunnel_service_add(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SPICE_GNUC_UNUSED intptr_t ptr_size; + uint32_t n_ptr=0; + PointerInfo ptr_info[2]; + size_t name__extra_size; + size_t description__extra_size; + size_t u__nw_size; + uint16_t type__value; + SpiceMsgcTunnelAddGenericService *out; + uint32_t i; + + { /* name */ + uint32_t name__value; + uint32_t name__array__nw_size; + pos = (start + 14); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + name__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + name__value >= message_end)) { + goto error; + } + name__array__nw_size = spice_strnlen((char *)message_start + name__value, message_end - (message_start + name__value)); + if (SPICE_UNLIKELY(*(message_start + name__value + name__array__nw_size) != 0)) { + goto error; + } + /* @nocopy, so no extra size */ + name__extra_size = 0; + } + + { /* description */ + uint32_t description__value; + uint32_t description__array__nw_size; + pos = (start + 18); + if (SPICE_UNLIKELY(pos + 4 > message_end)) { + goto error; + } + description__value = read_uint32(pos); + if (SPICE_UNLIKELY(message_start + description__value >= message_end)) { + goto error; + } + description__array__nw_size = spice_strnlen((char *)message_start + description__value, message_end - (message_start + description__value)); + if (SPICE_UNLIKELY(*(message_start + description__value + description__array__nw_size) != 0)) { + goto error; + } + /* @nocopy, so no extra size */ + description__extra_size = 0; + } + + { /* u */ + pos = start + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + type__value = read_uint16(pos); + if (type__value == SPICE_TUNNEL_SERVICE_TYPE_IPP) { + SPICE_GNUC_UNUSED uint8_t *start2 = (start + 22); + size_t u_u__nw_size; + uint16_t type__value; + { /* u */ + uint32_t u_u__nelements; + pos = start2 + 0; + if (SPICE_UNLIKELY(pos + 2 > message_end)) { + goto error; + } + type__value = read_uint16(pos); + if (type__value == SPICE_TUNNEL_IP_TYPE_IPv4) { + u_u__nelements = 4; + + u_u__nw_size = u_u__nelements; + } else { + u_u__nw_size = 0; + } + + } + + u__nw_size = 2 + u_u__nw_size; + } else { + u__nw_size = 0; + } + + } + + nw_size = 22 + u__nw_size; + mem_size = sizeof(SpiceMsgcTunnelAddGenericService) + name__extra_size + description__extra_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelAddGenericService); + in = start; + + out = (SpiceMsgcTunnelAddGenericService *)data; + + out->type = consume_uint16(&in); + out->id = consume_uint32(&in); + out->group = consume_uint32(&in); + out->port = consume_uint32(&in); + /* Reuse data from network message */ + out->name = (size_t)(message_start + consume_uint32(&in)); + /* Reuse data from network message */ + out->description = (size_t)(message_start + consume_uint32(&in)); + if (out->type == SPICE_TUNNEL_SERVICE_TYPE_IPP) { + out->u.ip.type = consume_uint16(&in); + if (out->u.ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) { + uint32_t ipv4__nelements; + ipv4__nelements = 4; + memcpy(out->u.ip.u.ipv4, in, ipv4__nelements); + in += ipv4__nelements; + } + } + + assert(in <= message_end); + + for (i = 0; i < n_ptr; i++) { + if (ptr_info[i].offset == 0) { + *ptr_info[i].dest = NULL; + } else { + /* Align to 32 bit */ + end = (uint8_t *)SPICE_ALIGN((size_t)end, 4); + *ptr_info[i].dest = (void *)end; + end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i], minor); + if (SPICE_UNLIKELY(end == NULL)) { + goto error; + } + } + } + + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_service_remove(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelRemoveService *out; + + nw_size = 4; + mem_size = sizeof(SpiceMsgcTunnelRemoveService); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelRemoveService); + in = start; + + out = (SpiceMsgcTunnelRemoveService *)data; + + out->id = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_open_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketOpenAck *out; + + nw_size = 6; + mem_size = sizeof(SpiceMsgcTunnelSocketOpenAck); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketOpenAck); + in = start; + + out = (SpiceMsgcTunnelSocketOpenAck *)data; + + out->connection_id = consume_uint16(&in); + out->tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_open_nack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketOpenNack *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcTunnelSocketOpenNack); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketOpenNack); + in = start; + + out = (SpiceMsgcTunnelSocketOpenNack *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_fin(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketFin *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcTunnelSocketFin); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketFin); + in = start; + + out = (SpiceMsgcTunnelSocketFin *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_closed(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketClosed *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcTunnelSocketClosed); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketClosed); + in = start; + + out = (SpiceMsgcTunnelSocketClosed *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_closed_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketClosedAck *out; + + nw_size = 2; + mem_size = sizeof(SpiceMsgcTunnelSocketClosedAck); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketClosedAck); + in = start; + + out = (SpiceMsgcTunnelSocketClosedAck *)data; + + out->connection_id = consume_uint16(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_data(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + size_t data__nw_size, data__mem_size; + uint32_t data__nelements; + SpiceMsgcTunnelSocketData *out; + + { /* data */ + data__nelements = message_end - (start + 2); + + data__nw_size = data__nelements; + data__mem_size = sizeof(uint8_t) * data__nelements; + } + + nw_size = 2 + data__nw_size; + mem_size = sizeof(SpiceMsgcTunnelSocketData) + data__mem_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketData); + in = start; + + out = (SpiceMsgcTunnelSocketData *)data; + + out->connection_id = consume_uint16(&in); + memcpy(out->data, in, data__nelements); + in += data__nelements; + end += data__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_msgc_tunnel_socket_token(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcTunnelSocketTokens *out; + + nw_size = 6; + mem_size = sizeof(SpiceMsgcTunnelSocketTokens); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcTunnelSocketTokens); + in = start; + + out = (SpiceMsgcTunnelSocketTokens *)data; + + out->connection_id = consume_uint16(&in); + out->num_tokens = consume_uint32(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_TunnelChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[9] = { + parse_msgc_tunnel_service_add, + parse_msgc_tunnel_service_remove, + parse_msgc_tunnel_socket_open_ack, + parse_msgc_tunnel_socket_open_nack, + parse_msgc_tunnel_socket_fin, + parse_msgc_tunnel_socket_closed, + parse_msgc_tunnel_socket_closed_ack, + parse_msgc_tunnel_socket_data, + parse_msgc_tunnel_socket_token + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 110) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + +#ifdef USE_SMARTCARD + +static uint8_t * parse_msgc_smartcard_reader_add(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + uint8_t *in, *end; + size_t reader_name__nw_size; + uint32_t reader_name__nelements; + VSCMsgReaderAdd *out; + + { /* reader_name */ + reader_name__nelements = message_end - (start + 0); + + reader_name__nw_size = reader_name__nelements; + } + + nw_size = 0 + reader_name__nw_size; + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(VSCMsgReaderAdd); + in = start; + + out = (VSCMsgReaderAdd *)data; + + memcpy(out->reader_name, in, reader_name__nelements); + in += reader_name__nelements; + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_SmartcardChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[1] = { + parse_msgc_smartcard_reader_add + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 102) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} +#endif /* USE_SMARTCARD */ + + + +static uint8_t * parse_UsbredirChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[1] = { + parse_SpiceMsgData + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 102) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_msgc_port_event(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message) +{ + SPICE_GNUC_UNUSED uint8_t *pos; + uint8_t *start = message_start; + uint8_t *data = NULL; + size_t nw_size; + size_t mem_size; + uint8_t *in, *end; + SpiceMsgcPortEvent *out; + + nw_size = 1; + mem_size = sizeof(SpiceMsgcPortEvent); + + /* Check if message fits in reported side */ + if (start + nw_size > message_end) { + return NULL; + } + + /* Validated extents and calculated size */ + data = (uint8_t *)malloc(mem_size); + if (SPICE_UNLIKELY(data == NULL)) { + goto error; + } + end = data + sizeof(SpiceMsgcPortEvent); + in = start; + + out = (SpiceMsgcPortEvent *)data; + + out->event = consume_uint8(&in); + + assert(in <= message_end); + assert(end <= data + mem_size); + + *size = end - data; + *free_message = (message_destructor_t) free; + return data; + + error: + if (data != NULL) { + free(data); + } + return NULL; +} + +static uint8_t * parse_PortChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[1] = { + parse_SpiceMsgData + }; + static parse_msg_func_t funcs3[1] = { + parse_msgc_port_event + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 102) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 201 && message_type < 202) { + return funcs3[message_type-201](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + + + +static uint8_t * parse_WebDAVChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + static parse_msg_func_t funcs1[6] = { + parse_msgc_ack_sync, + parse_SpiceMsgEmpty, + parse_msgc_pong, + parse_SpiceMsgEmpty, + parse_SpiceMsgData, + parse_msgc_disconnecting + }; + static parse_msg_func_t funcs2[1] = { + parse_SpiceMsgData + }; + static parse_msg_func_t funcs3[1] = { + parse_msgc_port_event + }; + if (message_type >= 1 && message_type < 7) { + return funcs1[message_type-1](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 101 && message_type < 102) { + return funcs2[message_type-101](message_start, message_end, minor, size_out, free_message); + } else if (message_type >= 201 && message_type < 202) { + return funcs3[message_type-201](message_start, message_end, minor, size_out, free_message); + } + return NULL; +} + +spice_parse_channel_func_t spice_get_client_channel_parser(uint32_t channel, unsigned int *max_message_type) +{ + static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[12] = { + { NULL, 0 }, + { parse_MainChannel_msgc, 111}, + { parse_DisplayChannel_msgc, 104}, + { parse_InputsChannel_msgc, 114}, + { parse_CursorChannel_msgc, 6}, + { parse_PlaybackChannel_msgc, 6}, + { parse_RecordChannel_msgc, 103}, + { parse_TunnelChannel_msgc, 109}, +#ifdef USE_SMARTCARD + { parse_SmartcardChannel_msgc, 101}, +#else /* USE_SMARTCARD */ + { NULL, 0 }, +#endif /* USE_SMARTCARD */ + { parse_UsbredirChannel_msgc, 101}, + { parse_PortChannel_msgc, 201}, + { parse_WebDAVChannel_msgc, 201} + }; + if (channel < 12) { + if (max_message_type != NULL) { + *max_message_type = channels[channel].max_messages; + } + return channels[channel].func; + } + return NULL; +} + +uint8_t * spice_parse_reply(uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message) +{ + spice_parse_channel_func_t func; + func = spice_get_client_channel_parser(channel, NULL); + if (func != NULL) { + return func(message_start, message_end, message_type, minor, size_out, free_message); + } + return NULL; +} diff --git a/spice-common/common/generated_server_marshallers.c b/spice-common/common/generated_server_marshallers.c new file mode 100644 index 0000000..0f4978d --- /dev/null +++ b/spice-common/common/generated_server_marshallers.c @@ -0,0 +1,1939 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "common/marshaller.h" + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#pragma warning(disable:4018) +#endif + +void spice_marshall_msg_migrate(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMigrate *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMigrate *src; + src = (SpiceMsgMigrate *)msg; + + spice_marshaller_add_uint32(m, src->flags); +} + +void spice_marshall_SpiceMsgData(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +void spice_marshall_msg_set_ack(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgSetAck *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgSetAck *src; + src = (SpiceMsgSetAck *)msg; + + spice_marshaller_add_uint32(m, src->generation); + spice_marshaller_add_uint32(m, src->window); +} + +void spice_marshall_msg_ping(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPing *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPing *src; + src = (SpiceMsgPing *)msg; + + spice_marshaller_add_uint32(m, src->id); + spice_marshaller_add_uint64(m, src->timestamp); + /* Remaining data must be appended manually */ +} + +void spice_marshall_msg_wait_for_channels(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgWaitForChannels *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgWaitForChannels *src; + SpiceWaitForChannel *wait_list__element; + uint32_t i; + src = (SpiceMsgWaitForChannels *)msg; + + spice_marshaller_add_uint8(m, src->wait_count); + wait_list__element = src->wait_list; + for (i = 0; i < src->wait_count; i++) { + SpiceWaitForChannel *src2; + src2 = (SpiceWaitForChannel *)wait_list__element; + + spice_marshaller_add_uint8(m, src2->channel_type); + spice_marshaller_add_uint8(m, src2->channel_id); + spice_marshaller_add_uint64(m, src2->message_serial); + wait_list__element++; + } +} + +void spice_marshall_msg_disconnecting(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisconnect *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisconnect *src; + src = (SpiceMsgDisconnect *)msg; + + spice_marshaller_add_uint64(m, src->time_stamp); + spice_marshaller_add_uint32(m, src->reason); +} + +void spice_marshall_msg_notify(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgNotify *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgNotify *src; + src = (SpiceMsgNotify *)msg; + + spice_marshaller_add_uint64(m, src->time_stamp); + spice_marshaller_add_uint32(m, src->severity); + spice_marshaller_add_uint32(m, src->visibilty); + spice_marshaller_add_uint32(m, src->what); + spice_marshaller_add_uint32(m, src->message_len); + /* Don't marshall @nomarshal message */ +} + +void spice_marshall_SpiceMsgEmpty(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgEmpty *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; +} + +SPICE_GNUC_UNUSED static void spice_marshall_array_uint8(SpiceMarshaller *m, uint8_t *ptr, unsigned count) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + uint32_t i; + + for (i = 0; i < count; i++) { + spice_marshaller_add_uint8(m, *ptr++); + } +} + +void spice_marshall_msg_main_migrate_begin(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainMigrationBegin *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainMigrationBegin *src; + src = (SpiceMsgMainMigrationBegin *)msg; + + /* dst_info */ { + spice_marshaller_add_uint16(m, src->dst_info.port); + spice_marshaller_add_uint16(m, src->dst_info.sport); + spice_marshaller_add_uint32(m, src->dst_info.host_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + spice_marshall_array_uint8(m2, src->dst_info.host_data, src->dst_info.host_size); + spice_marshaller_add_uint32(m, src->dst_info.cert_subject_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->dst_info.cert_subject_data != NULL) { + spice_marshall_array_uint8(m2, src->dst_info.cert_subject_data, src->dst_info.cert_subject_size); + } + } +} + +void spice_marshall_msg_main_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainInit *src; + src = (SpiceMsgMainInit *)msg; + + spice_marshaller_add_uint32(m, src->session_id); + spice_marshaller_add_uint32(m, src->display_channels_hint); + spice_marshaller_add_uint32(m, src->supported_mouse_modes); + spice_marshaller_add_uint32(m, src->current_mouse_mode); + spice_marshaller_add_uint32(m, src->agent_connected); + spice_marshaller_add_uint32(m, src->agent_tokens); + spice_marshaller_add_uint32(m, src->multi_media_time); + spice_marshaller_add_uint32(m, src->ram_hint); +} + +void spice_marshall_msg_main_channels_list(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgChannels *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgChannels *src; + SpiceChannelId *channels__element; + uint32_t i; + src = (SpiceMsgChannels *)msg; + + spice_marshaller_add_uint32(m, src->num_of_channels); + channels__element = src->channels; + for (i = 0; i < src->num_of_channels; i++) { + SpiceChannelId *src2; + src2 = (SpiceChannelId *)channels__element; + + spice_marshaller_add_uint8(m, src2->type); + spice_marshaller_add_uint8(m, src2->id); + channels__element++; + } +} + +void spice_marshall_msg_main_mouse_mode(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainMouseMode *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainMouseMode *src; + src = (SpiceMsgMainMouseMode *)msg; + + spice_marshaller_add_uint16(m, src->supported_modes); + spice_marshaller_add_uint16(m, src->current_mode); +} + +void spice_marshall_msg_main_multi_media_time(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainMultiMediaTime *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainMultiMediaTime *src; + src = (SpiceMsgMainMultiMediaTime *)msg; + + spice_marshaller_add_uint32(m, src->time); +} + +void spice_marshall_msg_main_agent_disconnected(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainAgentDisconnect *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainAgentDisconnect *src; + src = (SpiceMsgMainAgentDisconnect *)msg; + + spice_marshaller_add_uint32(m, src->error_code); +} + +void spice_marshall_msg_main_agent_token(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainAgentTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainAgentTokens *src; + src = (SpiceMsgMainAgentTokens *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +void spice_marshall_msg_main_migrate_switch_host(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainMigrationSwitchHost *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainMigrationSwitchHost *src; + src = (SpiceMsgMainMigrationSwitchHost *)msg; + + spice_marshaller_add_uint16(m, src->port); + spice_marshaller_add_uint16(m, src->sport); + spice_marshaller_add_uint32(m, src->host_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->host_data != NULL) { + spice_marshall_array_uint8(m2, src->host_data, src->host_size); + } + spice_marshaller_add_uint32(m, src->cert_subject_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->cert_subject_data != NULL) { + spice_marshall_array_uint8(m2, src->cert_subject_data, src->cert_subject_size); + } +} + +void spice_marshall_msg_main_name(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainName *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainName *src; + uint8_t *name__element; + uint32_t i; + src = (SpiceMsgMainName *)msg; + + spice_marshaller_add_uint32(m, src->name_len); + name__element = src->name; + for (i = 0; i < src->name_len; i++) { + spice_marshaller_add_uint8(m, *name__element); + name__element++; + } +} + +void spice_marshall_msg_main_uuid(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainUuid *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainUuid *src; + uint8_t *uuid__element; + uint32_t i; + src = (SpiceMsgMainUuid *)msg; + + uuid__element = src->uuid; + for (i = 0; i < 16; i++) { + spice_marshaller_add_uint8(m, *uuid__element); + uuid__element++; + } +} + +void spice_marshall_msg_main_agent_connected_tokens(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainAgentConnectedTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainAgentConnectedTokens *src; + src = (SpiceMsgMainAgentConnectedTokens *)msg; + + spice_marshaller_add_uint32(m, src->num_tokens); +} + +void spice_marshall_msg_main_migrate_begin_seamless(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainMigrateBeginSeamless *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainMigrateBeginSeamless *src; + src = (SpiceMsgMainMigrateBeginSeamless *)msg; + + /* dst_info */ { + spice_marshaller_add_uint16(m, src->dst_info.port); + spice_marshaller_add_uint16(m, src->dst_info.sport); + spice_marshaller_add_uint32(m, src->dst_info.host_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + spice_marshall_array_uint8(m2, src->dst_info.host_data, src->dst_info.host_size); + spice_marshaller_add_uint32(m, src->dst_info.cert_subject_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->dst_info.cert_subject_data != NULL) { + spice_marshall_array_uint8(m2, src->dst_info.cert_subject_data, src->dst_info.cert_subject_size); + } + } + spice_marshaller_add_uint32(m, src->src_mig_version); +} + +void spice_marshall_msg_display_mode(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayMode *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayMode *src; + src = (SpiceMsgDisplayMode *)msg; + + spice_marshaller_add_uint32(m, src->x_res); + spice_marshaller_add_uint32(m, src->y_res); + spice_marshaller_add_uint32(m, src->bits); +} + +void spice_marshall_msg_display_copy_bits(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayCopyBits *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayCopyBits *src; + uint32_t i; + src = (SpiceMsgDisplayCopyBits *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* src_pos */ { + spice_marshaller_add_int32(m, src->src_pos.x); + spice_marshaller_add_int32(m, src->src_pos.y); + } +} + +void spice_marshall_msg_display_inval_list(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceResourceList *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceResourceList *src; + SpiceResourceID *resources__element; + uint32_t i; + src = (SpiceResourceList *)msg; + + spice_marshaller_add_uint16(m, src->count); + resources__element = src->resources; + for (i = 0; i < src->count; i++) { + SpiceResourceID *src2; + src2 = (SpiceResourceID *)resources__element; + + spice_marshaller_add_uint8(m, src2->type); + spice_marshaller_add_uint64(m, src2->id); + resources__element++; + } +} + +void spice_marshall_msg_display_inval_all_pixmaps(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgWaitForChannels *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgWaitForChannels *src; + SpiceWaitForChannel *wait_list__element; + uint32_t i; + src = (SpiceMsgWaitForChannels *)msg; + + spice_marshaller_add_uint8(m, src->wait_count); + wait_list__element = src->wait_list; + for (i = 0; i < src->wait_count; i++) { + SpiceWaitForChannel *src2; + src2 = (SpiceWaitForChannel *)wait_list__element; + + spice_marshaller_add_uint8(m, src2->channel_type); + spice_marshaller_add_uint8(m, src2->channel_id); + spice_marshaller_add_uint64(m, src2->message_serial); + wait_list__element++; + } +} + +void spice_marshall_msg_display_inval_palette(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayInvalOne *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayInvalOne *src; + src = (SpiceMsgDisplayInvalOne *)msg; + + spice_marshaller_add_uint64(m, src->id); +} + +void spice_marshall_msg_display_stream_create(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamCreate *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamCreate *src; + uint32_t i; + src = (SpiceMsgDisplayStreamCreate *)msg; + + spice_marshaller_add_uint32(m, src->surface_id); + spice_marshaller_add_uint32(m, src->id); + spice_marshaller_add_uint8(m, src->flags); + spice_marshaller_add_uint8(m, src->codec_type); + spice_marshaller_add_uint64(m, src->stamp); + spice_marshaller_add_uint32(m, src->stream_width); + spice_marshaller_add_uint32(m, src->stream_height); + spice_marshaller_add_uint32(m, src->src_width); + spice_marshaller_add_uint32(m, src->src_height); + /* dest */ { + spice_marshaller_add_int32(m, src->dest.top); + spice_marshaller_add_int32(m, src->dest.left); + spice_marshaller_add_int32(m, src->dest.bottom); + spice_marshaller_add_int32(m, src->dest.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->clip.type); + if (src->clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->clip.rects->num_rects); + rects__element = src->clip.rects->rects; + for (i = 0; i < src->clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } +} + +void spice_marshall_msg_display_stream_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamData *src; + src = (SpiceMsgDisplayStreamData *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.id); + spice_marshaller_add_uint32(m, src->base.multi_media_time); + } + spice_marshaller_add_uint32(m, src->data_size); + /* Don't marshall @nomarshal data */ +} + +void spice_marshall_msg_display_stream_clip(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamClip *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamClip *src; + uint32_t i; + src = (SpiceMsgDisplayStreamClip *)msg; + + spice_marshaller_add_uint32(m, src->id); + /* clip */ { + spice_marshaller_add_uint8(m, src->clip.type); + if (src->clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->clip.rects->num_rects); + rects__element = src->clip.rects->rects; + for (i = 0; i < src->clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } +} + +void spice_marshall_msg_display_stream_destroy(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamDestroy *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamDestroy *src; + src = (SpiceMsgDisplayStreamDestroy *)msg; + + spice_marshaller_add_uint32(m, src->id); +} + +void spice_marshall_msg_display_draw_fill(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawFill *msg, SpiceMarshaller **brush_pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *brush_pat_out = NULL; + *mask_bitmap_out = NULL; +} + +void spice_marshall_msg_display_draw_opaque(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawOpaque *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *src_bitmap_out = NULL; + *pat_out = NULL; + *mask_bitmap_out = NULL; +} + +void spice_marshall_Palette(SpiceMarshaller *m, SpicePalette *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpicePalette *src; + uint32_t *ents__element; + uint32_t i; + + src = (SpicePalette *)ptr; + + spice_marshaller_add_uint64(m, src->unique); + spice_marshaller_add_uint16(m, src->num_ents); + ents__element = src->ents; + for (i = 0; i < src->num_ents; i++) { + spice_marshaller_add_uint32(m, *ents__element); + ents__element++; + } +} + +void spice_marshall_Image(SpiceMarshaller *m, SpiceImage *ptr, SpiceMarshaller **bitmap_palette_out, SpiceMarshaller **lzplt_palette_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceImage *src; + *bitmap_palette_out = NULL; + *lzplt_palette_out = NULL; + + src = (SpiceImage *)ptr; + + /* descriptor */ { + spice_marshaller_add_uint64(m, src->descriptor.id); + spice_marshaller_add_uint8(m, src->descriptor.type); + spice_marshaller_add_uint8(m, src->descriptor.flags); + spice_marshaller_add_uint32(m, src->descriptor.width); + spice_marshaller_add_uint32(m, src->descriptor.height); + } + if (src->descriptor.type == SPICE_IMAGE_TYPE_BITMAP) { + spice_marshaller_add_uint8(m, src->u.bitmap.format); + spice_marshaller_add_uint8(m, src->u.bitmap.flags); + spice_marshaller_add_uint32(m, src->u.bitmap.x); + spice_marshaller_add_uint32(m, src->u.bitmap.y); + spice_marshaller_add_uint32(m, src->u.bitmap.stride); + if ((src->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + spice_marshaller_add_uint64(m, src->u.bitmap.palette_id); + } else if (1) { + *bitmap_palette_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_QUIC) { + spice_marshaller_add_uint32(m, src->u.quic.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB || src->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB) { + spice_marshaller_add_uint32(m, src->u.lz_rgb.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_JPEG) { + spice_marshaller_add_uint32(m, src->u.jpeg.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_LZ4) { + spice_marshaller_add_uint32(m, src->u.lz4.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { + spice_marshaller_add_uint8(m, src->u.lz_plt.flags); + spice_marshaller_add_uint32(m, src->u.lz_plt.data_size); + if ((src->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { + spice_marshaller_add_uint64(m, src->u.lz_plt.palette_id); + } else if (1) { + *lzplt_palette_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) { + spice_marshaller_add_uint32(m, src->u.zlib_glz.glz_data_size); + spice_marshaller_add_uint32(m, src->u.zlib_glz.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_JPEG_ALPHA) { + spice_marshaller_add_uint8(m, src->u.jpeg_alpha.flags); + spice_marshaller_add_uint32(m, src->u.jpeg_alpha.jpeg_size); + spice_marshaller_add_uint32(m, src->u.jpeg_alpha.data_size); + /* Don't marshall @nomarshal data */ + } else if (src->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + spice_marshaller_add_uint32(m, src->u.surface.surface_id); + } +} + +void spice_marshall_msg_display_draw_copy(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawCopy *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawCopy *src; + uint32_t i; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawCopy *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->data.src_area.top); + spice_marshaller_add_int32(m, src->data.src_area.left); + spice_marshaller_add_int32(m, src->data.src_area.bottom); + spice_marshaller_add_int32(m, src->data.src_area.right); + } + spice_marshaller_add_uint16(m, src->data.rop_descriptor); + spice_marshaller_add_uint8(m, src->data.scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->data.mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->data.mask.pos.x); + spice_marshaller_add_int32(m, src->data.mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } +} + +void spice_marshall_msg_display_draw_blend(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawBlend *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawBlend *src; + uint32_t i; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawBlend *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->data.src_area.top); + spice_marshaller_add_int32(m, src->data.src_area.left); + spice_marshaller_add_int32(m, src->data.src_area.bottom); + spice_marshaller_add_int32(m, src->data.src_area.right); + } + spice_marshaller_add_uint16(m, src->data.rop_descriptor); + spice_marshaller_add_uint8(m, src->data.scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->data.mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->data.mask.pos.x); + spice_marshaller_add_int32(m, src->data.mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } +} + +void spice_marshall_msg_display_draw_blackness(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawBlackness *msg, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawBlackness *src; + uint32_t i; + *mask_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawBlackness *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + /* mask */ { + spice_marshaller_add_uint8(m, src->data.mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->data.mask.pos.x); + spice_marshaller_add_int32(m, src->data.mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } +} + +void spice_marshall_msg_display_draw_whiteness(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawWhiteness *msg, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawWhiteness *src; + uint32_t i; + *mask_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawWhiteness *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + /* mask */ { + spice_marshaller_add_uint8(m, src->data.mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->data.mask.pos.x); + spice_marshaller_add_int32(m, src->data.mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } +} + +void spice_marshall_msg_display_draw_invers(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawInvers *msg, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawInvers *src; + uint32_t i; + *mask_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawInvers *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + /* mask */ { + spice_marshaller_add_uint8(m, src->data.mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->data.mask.pos.x); + spice_marshaller_add_int32(m, src->data.mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } +} + +void spice_marshall_msg_display_draw_rop3(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawRop3 *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *src_bitmap_out = NULL; + *pat_out = NULL; + *mask_bitmap_out = NULL; +} + +void spice_marshall_msg_display_draw_stroke(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawStroke *msg, SpiceMarshaller **style_out, SpiceMarshaller **pat_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *style_out = NULL; + *pat_out = NULL; +} + +void spice_marshall_msg_display_draw_text(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawText *msg, SpiceMarshaller **fore_brush_pat_out, SpiceMarshaller **back_brush_pat_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *fore_brush_pat_out = NULL; + *back_brush_pat_out = NULL; +} + +void spice_marshall_msg_display_draw_transparent(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawTransparent *msg, SpiceMarshaller **src_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawTransparent *src; + uint32_t i; + *src_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawTransparent *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->data.src_area.top); + spice_marshaller_add_int32(m, src->data.src_area.left); + spice_marshaller_add_int32(m, src->data.src_area.bottom); + spice_marshaller_add_int32(m, src->data.src_area.right); + } + spice_marshaller_add_uint32(m, src->data.src_color); + spice_marshaller_add_uint32(m, src->data.true_color); + } +} + +void spice_marshall_msg_display_draw_alpha_blend(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawAlphaBlend *msg, SpiceMarshaller **src_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayDrawAlphaBlend *src; + uint32_t i; + *src_bitmap_out = NULL; + src = (SpiceMsgDisplayDrawAlphaBlend *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->base.box.top); + spice_marshaller_add_int32(m, src->base.box.left); + spice_marshaller_add_int32(m, src->base.box.bottom); + spice_marshaller_add_int32(m, src->base.box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->base.clip.type); + if (src->base.clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->base.clip.rects->num_rects); + rects__element = src->base.clip.rects->rects; + for (i = 0; i < src->base.clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } + } + /* data */ { + spice_marshaller_add_uint8(m, src->data.alpha_flags); + spice_marshaller_add_uint8(m, src->data.alpha); + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->data.src_area.top); + spice_marshaller_add_int32(m, src->data.src_area.left); + spice_marshaller_add_int32(m, src->data.src_area.bottom); + spice_marshaller_add_int32(m, src->data.src_area.right); + } + } +} + +void spice_marshall_msg_display_surface_create(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgSurfaceCreate *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgSurfaceCreate *src; + src = (SpiceMsgSurfaceCreate *)msg; + + spice_marshaller_add_uint32(m, src->surface_id); + spice_marshaller_add_uint32(m, src->width); + spice_marshaller_add_uint32(m, src->height); + spice_marshaller_add_uint32(m, src->format); + spice_marshaller_add_uint32(m, src->flags); +} + +void spice_marshall_msg_display_surface_destroy(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgSurfaceDestroy *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgSurfaceDestroy *src; + src = (SpiceMsgSurfaceDestroy *)msg; + + spice_marshaller_add_uint32(m, src->surface_id); +} + +void spice_marshall_msg_display_stream_data_sized(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamDataSized *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamDataSized *src; + src = (SpiceMsgDisplayStreamDataSized *)msg; + + /* base */ { + spice_marshaller_add_uint32(m, src->base.id); + spice_marshaller_add_uint32(m, src->base.multi_media_time); + } + spice_marshaller_add_uint32(m, src->width); + spice_marshaller_add_uint32(m, src->height); + /* dest */ { + spice_marshaller_add_int32(m, src->dest.top); + spice_marshaller_add_int32(m, src->dest.left); + spice_marshaller_add_int32(m, src->dest.bottom); + spice_marshaller_add_int32(m, src->dest.right); + } + spice_marshaller_add_uint32(m, src->data_size); + /* Don't marshall @nomarshal data */ +} + +void spice_marshall_msg_display_monitors_config(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayMonitorsConfig *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayMonitorsConfig *src; + SpiceHead *heads__element; + uint32_t i; + src = (SpiceMsgDisplayMonitorsConfig *)msg; + + spice_marshaller_add_uint16(m, src->count); + spice_marshaller_add_uint16(m, src->max_allowed); + heads__element = src->heads; + for (i = 0; i < src->count; i++) { + SpiceHead *src2; + src2 = (SpiceHead *)heads__element; + + spice_marshaller_add_uint32(m, src2->id); + spice_marshaller_add_uint32(m, src2->surface_id); + spice_marshaller_add_uint32(m, src2->width); + spice_marshaller_add_uint32(m, src2->height); + spice_marshaller_add_uint32(m, src2->x); + spice_marshaller_add_uint32(m, src2->y); + spice_marshaller_add_uint32(m, src2->flags); + heads__element++; + } +} + +void spice_marshall_msg_display_draw_composite(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayDrawComposite *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; +} + +void spice_marshall_msg_display_stream_activate_report(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayStreamActivateReport *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayStreamActivateReport *src; + src = (SpiceMsgDisplayStreamActivateReport *)msg; + + spice_marshaller_add_uint32(m, src->stream_id); + spice_marshaller_add_uint32(m, src->unique_id); + spice_marshaller_add_uint32(m, src->max_window_size); + spice_marshaller_add_uint32(m, src->timeout_ms); +} + +void spice_marshall_msg_display_gl_scanout_unix(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayGlScanoutUnix *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayGlScanoutUnix *src; + src = (SpiceMsgDisplayGlScanoutUnix *)msg; + + spice_marshaller_add_fd(m, src->drm_dma_buf_fd); + spice_marshaller_add_uint32(m, src->width); + spice_marshaller_add_uint32(m, src->height); + spice_marshaller_add_uint32(m, src->stride); + spice_marshaller_add_uint32(m, src->drm_fourcc_format); + spice_marshaller_add_uint32(m, src->flags); +} + +void spice_marshall_msg_display_gl_draw(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayGlDraw *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayGlDraw *src; + src = (SpiceMsgDisplayGlDraw *)msg; + + spice_marshaller_add_uint32(m, src->x); + spice_marshaller_add_uint32(m, src->y); + spice_marshaller_add_uint32(m, src->w); + spice_marshaller_add_uint32(m, src->h); +} + +void spice_marshall_msg_inputs_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgInputsInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgInputsInit *src; + src = (SpiceMsgInputsInit *)msg; + + spice_marshaller_add_uint16(m, src->keyboard_modifiers); +} + +void spice_marshall_msg_inputs_key_modifiers(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgInputsKeyModifiers *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgInputsKeyModifiers *src; + src = (SpiceMsgInputsKeyModifiers *)msg; + + spice_marshaller_add_uint16(m, src->modifiers); +} + +void spice_marshall_msg_cursor_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgCursorInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgCursorInit *src; + src = (SpiceMsgCursorInit *)msg; + + /* position */ { + spice_marshaller_add_int16(m, src->position.x); + spice_marshaller_add_int16(m, src->position.y); + } + spice_marshaller_add_uint16(m, src->trail_length); + spice_marshaller_add_uint16(m, src->trail_frequency); + spice_marshaller_add_uint8(m, src->visible); + /* cursor */ { + spice_marshaller_add_uint16(m, src->cursor.flags); + if (!(src->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) { + spice_marshaller_add_uint64(m, src->cursor.header.unique); + spice_marshaller_add_uint8(m, src->cursor.header.type); + spice_marshaller_add_uint16(m, src->cursor.header.width); + spice_marshaller_add_uint16(m, src->cursor.header.height); + spice_marshaller_add_uint16(m, src->cursor.header.hot_spot_x); + spice_marshaller_add_uint16(m, src->cursor.header.hot_spot_y); + } + /* Remaining data must be appended manually */ + } +} + +void spice_marshall_msg_cursor_set(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgCursorSet *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgCursorSet *src; + src = (SpiceMsgCursorSet *)msg; + + /* position */ { + spice_marshaller_add_int16(m, src->position.x); + spice_marshaller_add_int16(m, src->position.y); + } + spice_marshaller_add_uint8(m, src->visible); + /* cursor */ { + spice_marshaller_add_uint16(m, src->cursor.flags); + if (!(src->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) { + spice_marshaller_add_uint64(m, src->cursor.header.unique); + spice_marshaller_add_uint8(m, src->cursor.header.type); + spice_marshaller_add_uint16(m, src->cursor.header.width); + spice_marshaller_add_uint16(m, src->cursor.header.height); + spice_marshaller_add_uint16(m, src->cursor.header.hot_spot_x); + spice_marshaller_add_uint16(m, src->cursor.header.hot_spot_y); + } + /* Remaining data must be appended manually */ + } +} + +void spice_marshall_msg_cursor_move(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgCursorMove *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgCursorMove *src; + src = (SpiceMsgCursorMove *)msg; + + /* position */ { + spice_marshaller_add_int16(m, src->position.x); + spice_marshaller_add_int16(m, src->position.y); + } +} + +void spice_marshall_msg_cursor_trail(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgCursorTrail *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgCursorTrail *src; + src = (SpiceMsgCursorTrail *)msg; + + spice_marshaller_add_uint16(m, src->length); + spice_marshaller_add_uint16(m, src->frequency); +} + +void spice_marshall_msg_cursor_inval_one(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgDisplayInvalOne *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayInvalOne *src; + src = (SpiceMsgDisplayInvalOne *)msg; + + spice_marshaller_add_uint64(m, src->id); +} + +void spice_marshall_msg_playback_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPlaybackPacket *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPlaybackPacket *src; + src = (SpiceMsgPlaybackPacket *)msg; + + spice_marshaller_add_uint32(m, src->time); + /* Remaining data must be appended manually */ +} + +void spice_marshall_msg_playback_mode(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPlaybackMode *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPlaybackMode *src; + src = (SpiceMsgPlaybackMode *)msg; + + spice_marshaller_add_uint32(m, src->time); + spice_marshaller_add_uint16(m, src->mode); + /* Remaining data must be appended manually */ +} + +void spice_marshall_msg_playback_start(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPlaybackStart *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPlaybackStart *src; + src = (SpiceMsgPlaybackStart *)msg; + + spice_marshaller_add_uint32(m, src->channels); + spice_marshaller_add_uint16(m, src->format); + spice_marshaller_add_uint32(m, src->frequency); + spice_marshaller_add_uint32(m, src->time); +} + +void spice_marshall_SpiceMsgAudioVolume(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgAudioVolume *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgAudioVolume *src; + uint16_t *volume__element; + uint32_t i; + src = (SpiceMsgAudioVolume *)msg; + + spice_marshaller_add_uint8(m, src->nchannels); + volume__element = src->volume; + for (i = 0; i < src->nchannels; i++) { + spice_marshaller_add_uint16(m, *volume__element); + volume__element++; + } +} + +void spice_marshall_SpiceMsgAudioMute(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgAudioMute *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgAudioMute *src; + src = (SpiceMsgAudioMute *)msg; + + spice_marshaller_add_uint8(m, src->mute); +} + +void spice_marshall_msg_playback_latency(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPlaybackLatency *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPlaybackLatency *src; + src = (SpiceMsgPlaybackLatency *)msg; + + spice_marshaller_add_uint32(m, src->latency_ms); +} + +void spice_marshall_msg_record_start(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgRecordStart *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgRecordStart *src; + src = (SpiceMsgRecordStart *)msg; + + spice_marshaller_add_uint32(m, src->channels); + spice_marshaller_add_uint16(m, src->format); + spice_marshaller_add_uint32(m, src->frequency); +} + +void spice_marshall_msg_tunnel_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelInit *src; + src = (SpiceMsgTunnelInit *)msg; + + spice_marshaller_add_uint16(m, src->max_num_of_sockets); + spice_marshaller_add_uint32(m, src->max_socket_data_size); +} + +void spice_marshall_msg_tunnel_service_ip_map(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelServiceIpMap *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelServiceIpMap *src; + uint32_t i; + src = (SpiceMsgTunnelServiceIpMap *)msg; + + spice_marshaller_add_uint32(m, src->service_id); + /* virtual_ip */ { + uint8_t *ipv4__element; + spice_marshaller_add_uint16(m, src->virtual_ip.type); + if (src->virtual_ip.type == SPICE_TUNNEL_IP_TYPE_IPv4) { + ipv4__element = src->virtual_ip.u.ipv4; + for (i = 0; i < 4; i++) { + spice_marshaller_add_uint8(m, *ipv4__element); + ipv4__element++; + } + } + } +} + +void spice_marshall_msg_tunnel_socket_open(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketOpen *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketOpen *src; + src = (SpiceMsgTunnelSocketOpen *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + spice_marshaller_add_uint32(m, src->service_id); + spice_marshaller_add_uint32(m, src->tokens); +} + +void spice_marshall_msg_tunnel_socket_fin(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketFin *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketFin *src; + src = (SpiceMsgTunnelSocketFin *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +void spice_marshall_msg_tunnel_socket_close(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketClose *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketClose *src; + src = (SpiceMsgTunnelSocketClose *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +void spice_marshall_msg_tunnel_socket_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketData *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketData *src; + src = (SpiceMsgTunnelSocketData *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + /* Remaining data must be appended manually */ +} + +void spice_marshall_msg_tunnel_socket_closed_ack(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketClosedAck *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketClosedAck *src; + src = (SpiceMsgTunnelSocketClosedAck *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); +} + +void spice_marshall_msg_tunnel_socket_token(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgTunnelSocketTokens *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgTunnelSocketTokens *src; + src = (SpiceMsgTunnelSocketTokens *)msg; + + spice_marshaller_add_uint16(m, src->connection_id); + spice_marshaller_add_uint32(m, src->num_tokens); +} + +#ifdef USE_SMARTCARD +void spice_marshall_msg_smartcard_data(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgSmartcard *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgSmartcard *src; + src = (SpiceMsgSmartcard *)msg; + + spice_marshaller_add_uint32(m, src->type); + spice_marshaller_add_uint32(m, src->reader_id); + spice_marshaller_add_uint32(m, src->length); + /* Don't marshall @nomarshal data */ +} + +#endif /* USE_SMARTCARD */ +void spice_marshall_msg_port_init(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPortInit *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPortInit *src; + src = (SpiceMsgPortInit *)msg; + + spice_marshaller_add_uint32(m, src->name_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + spice_marshall_array_uint8(m2, src->name, src->name_size); + spice_marshaller_add_uint8(m, src->opened); +} + +void spice_marshall_msg_port_event(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgPortEvent *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgPortEvent *src; + src = (SpiceMsgPortEvent *)msg; + + spice_marshaller_add_uint8(m, src->event); +} + +void spice_marshall_String(SpiceMarshaller *m, SpiceString *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceString *src; + SpiceRasterGlyph * *glyphs__element; + uint32_t i; + uint32_t j; + + src = (SpiceString *)ptr; + + spice_marshaller_add_uint16(m, src->length); + spice_marshaller_add_uint8(m, src->flags); + if ((src->flags & SPICE_STRING_FLAGS_RASTER_A1)) { + glyphs__element = src->glyphs; + for (i = 0; i < src->length; i++) { + SpiceRasterGlyph *src2; + uint8_t *data__element; + src2 = (SpiceRasterGlyph *)*glyphs__element; + + /* render_pos */ { + spice_marshaller_add_int32(m, src2->render_pos.x); + spice_marshaller_add_int32(m, src2->render_pos.y); + } + /* glyph_origin */ { + spice_marshaller_add_int32(m, src2->glyph_origin.x); + spice_marshaller_add_int32(m, src2->glyph_origin.y); + } + spice_marshaller_add_uint16(m, src2->width); + spice_marshaller_add_uint16(m, src2->height); + data__element = src2->data; + for (j = 0; j < (unsigned) (((src2->width + 7) / 8 ) * src2->height); j++) { + spice_marshaller_add_uint8(m, *data__element); + data__element++; + } + glyphs__element++; + } + } else if ((src->flags & SPICE_STRING_FLAGS_RASTER_A4)) { + glyphs__element = src->glyphs; + for (i = 0; i < src->length; i++) { + SpiceRasterGlyph *src2; + uint8_t *data__element; + src2 = (SpiceRasterGlyph *)*glyphs__element; + + /* render_pos */ { + spice_marshaller_add_int32(m, src2->render_pos.x); + spice_marshaller_add_int32(m, src2->render_pos.y); + } + /* glyph_origin */ { + spice_marshaller_add_int32(m, src2->glyph_origin.x); + spice_marshaller_add_int32(m, src2->glyph_origin.y); + } + spice_marshaller_add_uint16(m, src2->width); + spice_marshaller_add_uint16(m, src2->height); + data__element = src2->data; + for (j = 0; j < (unsigned) (((4 * src2->width + 7) / 8 ) * src2->height); j++) { + spice_marshaller_add_uint8(m, *data__element); + data__element++; + } + glyphs__element++; + } + } else if ((src->flags & SPICE_STRING_FLAGS_RASTER_A8)) { + glyphs__element = src->glyphs; + for (i = 0; i < src->length; i++) { + SpiceRasterGlyph *src2; + uint8_t *data__element; + src2 = (SpiceRasterGlyph *)*glyphs__element; + + /* render_pos */ { + spice_marshaller_add_int32(m, src2->render_pos.x); + spice_marshaller_add_int32(m, src2->render_pos.y); + } + /* glyph_origin */ { + spice_marshaller_add_int32(m, src2->glyph_origin.x); + spice_marshaller_add_int32(m, src2->glyph_origin.y); + } + spice_marshaller_add_uint16(m, src2->width); + spice_marshaller_add_uint16(m, src2->height); + data__element = src2->data; + for (j = 0; j < (unsigned) (src2->width * src2->height); j++) { + spice_marshaller_add_uint8(m, *data__element); + data__element++; + } + glyphs__element++; + } + } +} +void spice_marshall_Rect(SpiceMarshaller *m, SpiceRect *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceRect *src; + + src = (SpiceRect *)ptr; + + spice_marshaller_add_int32(m, src->top); + spice_marshaller_add_int32(m, src->left); + spice_marshaller_add_int32(m, src->bottom); + spice_marshaller_add_int32(m, src->right); +} +void spice_marshall_Point(SpiceMarshaller *m, SpicePoint *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpicePoint *src; + + src = (SpicePoint *)ptr; + + spice_marshaller_add_int32(m, src->x); + spice_marshaller_add_int32(m, src->y); +} +void spice_marshall_DisplayBase(SpiceMarshaller *m, SpiceMsgDisplayBase *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgDisplayBase *src; + uint32_t i; + + src = (SpiceMsgDisplayBase *)ptr; + + spice_marshaller_add_uint32(m, src->surface_id); + /* box */ { + spice_marshaller_add_int32(m, src->box.top); + spice_marshaller_add_int32(m, src->box.left); + spice_marshaller_add_int32(m, src->box.bottom); + spice_marshaller_add_int32(m, src->box.right); + } + /* clip */ { + spice_marshaller_add_uint8(m, src->clip.type); + if (src->clip.type == SPICE_CLIP_TYPE_RECTS) { + SpiceRect *rects__element; + spice_marshaller_add_uint32(m, src->clip.rects->num_rects); + rects__element = src->clip.rects->rects; + for (i = 0; i < src->clip.rects->num_rects; i++) { + SpiceRect *src2; + src2 = (SpiceRect *)rects__element; + + spice_marshaller_add_int32(m, src2->top); + spice_marshaller_add_int32(m, src2->left); + spice_marshaller_add_int32(m, src2->bottom); + spice_marshaller_add_int32(m, src2->right); + rects__element++; + } + } + } +} +void spice_marshall_Fill(SpiceMarshaller *m, SpiceFill *ptr, SpiceMarshaller **brush_pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceFill *src; + *brush_pat_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceFill *)ptr; + + /* brush */ { + spice_marshaller_add_uint8(m, src->brush.type); + if (src->brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->brush.u.color); + } else if (src->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *brush_pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.y); + } + } + } + spice_marshaller_add_uint16(m, src->rop_descriptor); + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Opaque(SpiceMarshaller *m, SpiceOpaque *ptr, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceOpaque *src; + *src_bitmap_out = NULL; + *pat_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceOpaque *)ptr; + + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } + /* brush */ { + spice_marshaller_add_uint8(m, src->brush.type); + if (src->brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->brush.u.color); + } else if (src->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.y); + } + } + } + spice_marshaller_add_uint16(m, src->rop_descriptor); + spice_marshaller_add_uint8(m, src->scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Copy(SpiceMarshaller *m, SpiceCopy *ptr, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceCopy *src; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceCopy *)ptr; + + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } + spice_marshaller_add_uint16(m, src->rop_descriptor); + spice_marshaller_add_uint8(m, src->scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Blend(SpiceMarshaller *m, SpiceCopy *ptr, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceCopy *src; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceCopy *)ptr; + + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } + spice_marshaller_add_uint16(m, src->rop_descriptor); + spice_marshaller_add_uint8(m, src->scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Blackness(SpiceMarshaller *m, SpiceBlackness *ptr, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceBlackness *src; + *mask_bitmap_out = NULL; + + src = (SpiceBlackness *)ptr; + + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Whiteness(SpiceMarshaller *m, SpiceWhiteness *ptr, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceWhiteness *src; + *mask_bitmap_out = NULL; + + src = (SpiceWhiteness *)ptr; + + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Invers(SpiceMarshaller *m, SpiceInvers *ptr, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceInvers *src; + *mask_bitmap_out = NULL; + + src = (SpiceInvers *)ptr; + + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Rop3(SpiceMarshaller *m, SpiceRop3 *ptr, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceRop3 *src; + *src_bitmap_out = NULL; + *pat_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceRop3 *)ptr; + + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } + /* brush */ { + spice_marshaller_add_uint8(m, src->brush.type); + if (src->brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->brush.u.color); + } else if (src->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.y); + } + } + } + spice_marshaller_add_uint8(m, src->rop3); + spice_marshaller_add_uint8(m, src->scale_mode); + /* mask */ { + spice_marshaller_add_uint8(m, src->mask.flags); + /* pos */ { + spice_marshaller_add_int32(m, src->mask.pos.x); + spice_marshaller_add_int32(m, src->mask.pos.y); + } + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } +} +void spice_marshall_Path(SpiceMarshaller *m, SpicePath *ptr) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpicePath *src; + SpicePathSeg * *segments__element; + uint32_t i; + uint32_t j; + + src = (SpicePath *)ptr; + + spice_marshaller_add_uint32(m, src->num_segments); + segments__element = src->segments; + for (i = 0; i < src->num_segments; i++) { + SpicePathSeg *src2; + SpicePointFix *points__element; + src2 = (SpicePathSeg *)*segments__element; + + spice_marshaller_add_uint8(m, src2->flags); + spice_marshaller_add_uint32(m, src2->count); + points__element = src2->points; + for (j = 0; j < src2->count; j++) { + SpicePointFix *src3; + src3 = (SpicePointFix *)points__element; + + spice_marshaller_add_int32(m, src3->x); + spice_marshaller_add_int32(m, src3->y); + points__element++; + } + segments__element++; + } +} + +SPICE_GNUC_UNUSED static void spice_marshall_array_int32(SpiceMarshaller *m, int32_t *ptr, unsigned count) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + uint32_t i; + + for (i = 0; i < count; i++) { + spice_marshaller_add_int32(m, *ptr++); + } +} + +void spice_marshall_Stroke(SpiceMarshaller *m, SpiceStroke *ptr, SpiceMarshaller **style_out, SpiceMarshaller **pat_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceStroke *src; + *style_out = NULL; + *pat_out = NULL; + + src = (SpiceStroke *)ptr; + + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + spice_marshall_Path(m2, src->path); + /* attr */ { + spice_marshaller_add_uint8(m, src->attr.flags); + if ((src->attr.flags & SPICE_LINE_FLAGS_STYLED)) { + spice_marshaller_add_uint8(m, src->attr.style_nseg); + } + if ((src->attr.flags & SPICE_LINE_FLAGS_STYLED)) { + *style_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + } + /* brush */ { + spice_marshaller_add_uint8(m, src->brush.type); + if (src->brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->brush.u.color); + } else if (src->brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->brush.u.pattern.pos.y); + } + } + } + spice_marshaller_add_uint16(m, src->fore_mode); + spice_marshaller_add_uint16(m, src->back_mode); +} +void spice_marshall_Text(SpiceMarshaller *m, SpiceText *ptr, SpiceMarshaller **fore_brush_pat_out, SpiceMarshaller **back_brush_pat_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceText *src; + *fore_brush_pat_out = NULL; + *back_brush_pat_out = NULL; + + src = (SpiceText *)ptr; + + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + spice_marshall_String(m2, src->str); + /* back_area */ { + spice_marshaller_add_int32(m, src->back_area.top); + spice_marshaller_add_int32(m, src->back_area.left); + spice_marshaller_add_int32(m, src->back_area.bottom); + spice_marshaller_add_int32(m, src->back_area.right); + } + /* fore_brush */ { + spice_marshaller_add_uint8(m, src->fore_brush.type); + if (src->fore_brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->fore_brush.u.color); + } else if (src->fore_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *fore_brush_pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->fore_brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->fore_brush.u.pattern.pos.y); + } + } + } + /* back_brush */ { + spice_marshaller_add_uint8(m, src->back_brush.type); + if (src->back_brush.type == SPICE_BRUSH_TYPE_SOLID) { + spice_marshaller_add_uint32(m, src->back_brush.u.color); + } else if (src->back_brush.type == SPICE_BRUSH_TYPE_PATTERN) { + *back_brush_pat_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* pos */ { + spice_marshaller_add_int32(m, src->back_brush.u.pattern.pos.x); + spice_marshaller_add_int32(m, src->back_brush.u.pattern.pos.y); + } + } + } + spice_marshaller_add_uint16(m, src->fore_mode); + spice_marshaller_add_uint16(m, src->back_mode); +} +void spice_marshall_Transparent(SpiceMarshaller *m, SpiceTransparent *ptr, SpiceMarshaller **src_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceTransparent *src; + *src_bitmap_out = NULL; + + src = (SpiceTransparent *)ptr; + + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } + spice_marshaller_add_uint32(m, src->src_color); + spice_marshaller_add_uint32(m, src->true_color); +} +void spice_marshall_AlphaBlend(SpiceMarshaller *m, SpiceAlphaBlend *ptr, SpiceMarshaller **src_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceAlphaBlend *src; + *src_bitmap_out = NULL; + + src = (SpiceAlphaBlend *)ptr; + + spice_marshaller_add_uint8(m, src->alpha_flags); + spice_marshaller_add_uint8(m, src->alpha); + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + /* src_area */ { + spice_marshaller_add_int32(m, src->src_area.top); + spice_marshaller_add_int32(m, src->src_area.left); + spice_marshaller_add_int32(m, src->src_area.bottom); + spice_marshaller_add_int32(m, src->src_area.right); + } +} +void spice_marshall_Composite(SpiceMarshaller *m, SpiceComposite *ptr, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceComposite *src; + *src_bitmap_out = NULL; + *mask_bitmap_out = NULL; + + src = (SpiceComposite *)ptr; + + spice_marshaller_add_uint32(m, src->flags); + *src_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + if ((src->flags & SPICE_COMPOSITE_HAS_MASK)) { + *mask_bitmap_out = spice_marshaller_get_ptr_submarshaller(m, 0); + } + if ((src->flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) { + spice_marshaller_add_uint32(m, src->src_transform.t00); + spice_marshaller_add_uint32(m, src->src_transform.t01); + spice_marshaller_add_uint32(m, src->src_transform.t02); + spice_marshaller_add_uint32(m, src->src_transform.t10); + spice_marshaller_add_uint32(m, src->src_transform.t11); + spice_marshaller_add_uint32(m, src->src_transform.t12); + } + if ((src->flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) { + spice_marshaller_add_uint32(m, src->mask_transform.t00); + spice_marshaller_add_uint32(m, src->mask_transform.t01); + spice_marshaller_add_uint32(m, src->mask_transform.t02); + spice_marshaller_add_uint32(m, src->mask_transform.t10); + spice_marshaller_add_uint32(m, src->mask_transform.t11); + spice_marshaller_add_uint32(m, src->mask_transform.t12); + } + /* src_origin */ { + spice_marshaller_add_int16(m, src->src_origin.x); + spice_marshaller_add_int16(m, src->src_origin.y); + } + /* mask_origin */ { + spice_marshaller_add_int16(m, src->mask_origin.x); + spice_marshaller_add_int16(m, src->mask_origin.y); + } +} diff --git a/spice-common/common/generated_server_marshallers.h b/spice-common/common/generated_server_marshallers.h new file mode 100644 index 0000000..5d215ea --- /dev/null +++ b/spice-common/common/generated_server_marshallers.h @@ -0,0 +1,121 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include +#include +#include "common/marshaller.h" + +#ifndef _GENERATED_HEADERS_H +#define _GENERATED_HEADERS_H +void spice_marshall_msg_migrate(SpiceMarshaller *m, SpiceMsgMigrate *msg); +void spice_marshall_SpiceMsgData(SpiceMarshaller *m, SpiceMsgData *msg); +void spice_marshall_msg_set_ack(SpiceMarshaller *m, SpiceMsgSetAck *msg); +void spice_marshall_msg_ping(SpiceMarshaller *m, SpiceMsgPing *msg); +void spice_marshall_msg_wait_for_channels(SpiceMarshaller *m, SpiceMsgWaitForChannels *msg); +void spice_marshall_msg_disconnecting(SpiceMarshaller *m, SpiceMsgDisconnect *msg); +void spice_marshall_msg_notify(SpiceMarshaller *m, SpiceMsgNotify *msg); +void spice_marshall_SpiceMsgEmpty(SpiceMarshaller *m, SpiceMsgEmpty *msg); +void spice_marshall_msg_main_migrate_begin(SpiceMarshaller *m, SpiceMsgMainMigrationBegin *msg); +void spice_marshall_msg_main_init(SpiceMarshaller *m, SpiceMsgMainInit *msg); +void spice_marshall_msg_main_channels_list(SpiceMarshaller *m, SpiceMsgChannels *msg); +void spice_marshall_msg_main_mouse_mode(SpiceMarshaller *m, SpiceMsgMainMouseMode *msg); +void spice_marshall_msg_main_multi_media_time(SpiceMarshaller *m, SpiceMsgMainMultiMediaTime *msg); +void spice_marshall_msg_main_agent_disconnected(SpiceMarshaller *m, SpiceMsgMainAgentDisconnect *msg); +void spice_marshall_msg_main_agent_token(SpiceMarshaller *m, SpiceMsgMainAgentTokens *msg); +void spice_marshall_msg_main_migrate_switch_host(SpiceMarshaller *m, SpiceMsgMainMigrationSwitchHost *msg); +void spice_marshall_msg_main_name(SpiceMarshaller *m, SpiceMsgMainName *msg); +void spice_marshall_msg_main_uuid(SpiceMarshaller *m, SpiceMsgMainUuid *msg); +void spice_marshall_msg_main_agent_connected_tokens(SpiceMarshaller *m, SpiceMsgMainAgentConnectedTokens *msg); +void spice_marshall_msg_main_migrate_begin_seamless(SpiceMarshaller *m, SpiceMsgMainMigrateBeginSeamless *msg); +void spice_marshall_msg_display_mode(SpiceMarshaller *m, SpiceMsgDisplayMode *msg); +void spice_marshall_msg_display_copy_bits(SpiceMarshaller *m, SpiceMsgDisplayCopyBits *msg); +void spice_marshall_msg_display_inval_list(SpiceMarshaller *m, SpiceResourceList *msg); +void spice_marshall_msg_display_inval_all_pixmaps(SpiceMarshaller *m, SpiceMsgWaitForChannels *msg); +void spice_marshall_msg_display_inval_palette(SpiceMarshaller *m, SpiceMsgDisplayInvalOne *msg); +void spice_marshall_msg_display_stream_create(SpiceMarshaller *m, SpiceMsgDisplayStreamCreate *msg); +void spice_marshall_msg_display_stream_data(SpiceMarshaller *m, SpiceMsgDisplayStreamData *msg); +void spice_marshall_msg_display_stream_clip(SpiceMarshaller *m, SpiceMsgDisplayStreamClip *msg); +void spice_marshall_msg_display_stream_destroy(SpiceMarshaller *m, SpiceMsgDisplayStreamDestroy *msg); +void spice_marshall_msg_display_draw_fill(SpiceMarshaller *m, SpiceMsgDisplayDrawFill *msg, SpiceMarshaller **brush_pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_opaque(SpiceMarshaller *m, SpiceMsgDisplayDrawOpaque *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_copy(SpiceMarshaller *m, SpiceMsgDisplayDrawCopy *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Image(SpiceMarshaller *m, SpiceImage *msg, SpiceMarshaller **bitmap_palette_out, SpiceMarshaller **lzplt_palette_out); +void spice_marshall_Palette(SpiceMarshaller *m, SpicePalette *msg); +void spice_marshall_msg_display_draw_blend(SpiceMarshaller *m, SpiceMsgDisplayDrawBlend *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_blackness(SpiceMarshaller *m, SpiceMsgDisplayDrawBlackness *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_whiteness(SpiceMarshaller *m, SpiceMsgDisplayDrawWhiteness *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_invers(SpiceMarshaller *m, SpiceMsgDisplayDrawInvers *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_rop3(SpiceMarshaller *m, SpiceMsgDisplayDrawRop3 *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_draw_stroke(SpiceMarshaller *m, SpiceMsgDisplayDrawStroke *msg, SpiceMarshaller **style_out, SpiceMarshaller **pat_out); +void spice_marshall_msg_display_draw_text(SpiceMarshaller *m, SpiceMsgDisplayDrawText *msg, SpiceMarshaller **fore_brush_pat_out, SpiceMarshaller **back_brush_pat_out); +void spice_marshall_msg_display_draw_transparent(SpiceMarshaller *m, SpiceMsgDisplayDrawTransparent *msg, SpiceMarshaller **src_bitmap_out); +void spice_marshall_msg_display_draw_alpha_blend(SpiceMarshaller *m, SpiceMsgDisplayDrawAlphaBlend *msg, SpiceMarshaller **src_bitmap_out); +void spice_marshall_msg_display_surface_create(SpiceMarshaller *m, SpiceMsgSurfaceCreate *msg); +void spice_marshall_msg_display_surface_destroy(SpiceMarshaller *m, SpiceMsgSurfaceDestroy *msg); +void spice_marshall_msg_display_stream_data_sized(SpiceMarshaller *m, SpiceMsgDisplayStreamDataSized *msg); +void spice_marshall_msg_display_monitors_config(SpiceMarshaller *m, SpiceMsgDisplayMonitorsConfig *msg); +void spice_marshall_msg_display_draw_composite(SpiceMarshaller *m, SpiceMsgDisplayDrawComposite *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_msg_display_stream_activate_report(SpiceMarshaller *m, SpiceMsgDisplayStreamActivateReport *msg); +void spice_marshall_msg_display_gl_scanout_unix(SpiceMarshaller *m, SpiceMsgDisplayGlScanoutUnix *msg); +void spice_marshall_msg_display_gl_draw(SpiceMarshaller *m, SpiceMsgDisplayGlDraw *msg); +void spice_marshall_msg_inputs_init(SpiceMarshaller *m, SpiceMsgInputsInit *msg); +void spice_marshall_msg_inputs_key_modifiers(SpiceMarshaller *m, SpiceMsgInputsKeyModifiers *msg); +void spice_marshall_msg_cursor_init(SpiceMarshaller *m, SpiceMsgCursorInit *msg); +void spice_marshall_msg_cursor_set(SpiceMarshaller *m, SpiceMsgCursorSet *msg); +void spice_marshall_msg_cursor_move(SpiceMarshaller *m, SpiceMsgCursorMove *msg); +void spice_marshall_msg_cursor_trail(SpiceMarshaller *m, SpiceMsgCursorTrail *msg); +void spice_marshall_msg_cursor_inval_one(SpiceMarshaller *m, SpiceMsgDisplayInvalOne *msg); +void spice_marshall_msg_playback_data(SpiceMarshaller *m, SpiceMsgPlaybackPacket *msg); +void spice_marshall_msg_playback_mode(SpiceMarshaller *m, SpiceMsgPlaybackMode *msg); +void spice_marshall_msg_playback_start(SpiceMarshaller *m, SpiceMsgPlaybackStart *msg); +void spice_marshall_SpiceMsgAudioVolume(SpiceMarshaller *m, SpiceMsgAudioVolume *msg); +void spice_marshall_SpiceMsgAudioMute(SpiceMarshaller *m, SpiceMsgAudioMute *msg); +void spice_marshall_msg_playback_latency(SpiceMarshaller *m, SpiceMsgPlaybackLatency *msg); +void spice_marshall_msg_record_start(SpiceMarshaller *m, SpiceMsgRecordStart *msg); +void spice_marshall_msg_tunnel_init(SpiceMarshaller *m, SpiceMsgTunnelInit *msg); +void spice_marshall_msg_tunnel_service_ip_map(SpiceMarshaller *m, SpiceMsgTunnelServiceIpMap *msg); +void spice_marshall_msg_tunnel_socket_open(SpiceMarshaller *m, SpiceMsgTunnelSocketOpen *msg); +void spice_marshall_msg_tunnel_socket_fin(SpiceMarshaller *m, SpiceMsgTunnelSocketFin *msg); +void spice_marshall_msg_tunnel_socket_close(SpiceMarshaller *m, SpiceMsgTunnelSocketClose *msg); +void spice_marshall_msg_tunnel_socket_data(SpiceMarshaller *m, SpiceMsgTunnelSocketData *msg); +void spice_marshall_msg_tunnel_socket_closed_ack(SpiceMarshaller *m, SpiceMsgTunnelSocketClosedAck *msg); +void spice_marshall_msg_tunnel_socket_token(SpiceMarshaller *m, SpiceMsgTunnelSocketTokens *msg); +#ifdef USE_SMARTCARD +void spice_marshall_msg_smartcard_data(SpiceMarshaller *m, SpiceMsgSmartcard *msg); +#endif /* USE_SMARTCARD */ +void spice_marshall_msg_port_init(SpiceMarshaller *m, SpiceMsgPortInit *msg); +void spice_marshall_msg_port_event(SpiceMarshaller *m, SpiceMsgPortEvent *msg); +void spice_marshall_String(SpiceMarshaller *m, SpiceString *msg); +void spice_marshall_Rect(SpiceMarshaller *m, SpiceRect *msg); +void spice_marshall_Point(SpiceMarshaller *m, SpicePoint *msg); +void spice_marshall_DisplayBase(SpiceMarshaller *m, SpiceMsgDisplayBase *msg); +void spice_marshall_Fill(SpiceMarshaller *m, SpiceFill *msg, SpiceMarshaller **brush_pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Opaque(SpiceMarshaller *m, SpiceOpaque *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Copy(SpiceMarshaller *m, SpiceCopy *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Blend(SpiceMarshaller *m, SpiceCopy *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Blackness(SpiceMarshaller *m, SpiceBlackness *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Whiteness(SpiceMarshaller *m, SpiceWhiteness *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Invers(SpiceMarshaller *m, SpiceInvers *msg, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Rop3(SpiceMarshaller *m, SpiceRop3 *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **pat_out, SpiceMarshaller **mask_bitmap_out); +void spice_marshall_Stroke(SpiceMarshaller *m, SpiceStroke *msg, SpiceMarshaller **style_out, SpiceMarshaller **pat_out); +void spice_marshall_Path(SpiceMarshaller *m, SpicePath *msg); +void spice_marshall_Text(SpiceMarshaller *m, SpiceText *msg, SpiceMarshaller **fore_brush_pat_out, SpiceMarshaller **back_brush_pat_out); +void spice_marshall_Transparent(SpiceMarshaller *m, SpiceTransparent *msg, SpiceMarshaller **src_bitmap_out); +void spice_marshall_AlphaBlend(SpiceMarshaller *m, SpiceAlphaBlend *msg, SpiceMarshaller **src_bitmap_out); +void spice_marshall_Composite(SpiceMarshaller *m, SpiceComposite *msg, SpiceMarshaller **src_bitmap_out, SpiceMarshaller **mask_bitmap_out); +#endif diff --git a/spice-common/common/lines.c b/spice-common/common/lines.c new file mode 100644 index 0000000..e5097c4 --- /dev/null +++ b/spice-common/common/lines.c @@ -0,0 +1,3611 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/*********************************************************** + +Copyright 1989, 1998 The Open Group + +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. + +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 +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#ifdef _XOPEN_SOURCE +#include +#else +#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ +#include +#undef _XOPEN_SOURCE +#endif +#include "lines.h" +#include "mem.h" + +#define xalloc(i) spice_malloc(i) +#define xrealloc(a,b) spice_realloc(a,b) +#define xfree(i) free(i) + +typedef unsigned int CARD32; +typedef int Boolean; +typedef pixman_rectangle32_t xRectangle; +typedef SpicePoint DDXPointRec; +typedef DDXPointRec *DDXPointPtr; +typedef struct lineGC *GCPtr; + +/* largest positive value that can fit into a component of a point. + * Assumes that the point structure is {type x, y;} where type is + * a signed type. + */ +#define MAX_COORDINATE 2147483647 +#define MIN_COORDINATE -2147483647 + +#define miZeroLine spice_canvas_zero_line +#define miZeroDashLine spice_canvas_zero_dash_line +#define miWideDash spice_canvas_wide_dash_line +#define miWideLine spice_canvas_wide_line + +static inline int ICEIL (double x) +{ + int _cTmp = (int)x; + return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp + 1; +} + +typedef struct { + int count; /* number of spans */ + DDXPointPtr points; /* pointer to list of start points */ + int *widths; /* pointer to list of widths */ +} Spans; + +typedef struct { + int size; /* Total number of *Spans allocated */ + int count; /* Number of *Spans actually in group */ + Spans *group; /* List of Spans */ + int ymin, ymax; /* Min, max y values encountered */ +} SpanGroup; + +/* Initialize SpanGroup. MUST BE DONE before use. */ +static void miInitSpanGroup (SpanGroup * /*spanGroup */ + ); + +/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */ +static void miAppendSpans (SpanGroup * /*spanGroup */ , + SpanGroup * /*otherGroup */ , + Spans * /*spans */ + ); + +/* Paint a span group, insuring that each pixel is painted at most once */ +static void miFillUniqueSpanGroup (GCPtr /*pGC */ , + SpanGroup * /*spanGroup */ , + Boolean /* foreground */ + ); + +/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */ +static void miFreeSpanGroup (SpanGroup * /*spanGroup */ + ); + +/* Rops which must use span groups */ +#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2) +#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop)) + +/* + * Public definitions used for configuring basic pixelization aspects + * of the sample implementation line-drawing routines provided in + * {mfb,mi,cfb*} at run-time. + */ + +#define XDECREASING 4 +#define YDECREASING 2 +#define YMAJOR 1 + +#define OCTANT1 (1 << (YDECREASING)) +#define OCTANT2 (1 << (YDECREASING|YMAJOR)) +#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR)) +#define OCTANT4 (1 << (XDECREASING|YDECREASING)) +#define OCTANT5 (1 << (XDECREASING)) +#define OCTANT6 (1 << (XDECREASING|YMAJOR)) +#define OCTANT7 (1 << (YMAJOR)) +#define OCTANT8 (1 << (0)) + +#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8) + +#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5) + +/* + * Devices can configure the rendering of routines in mi, mfb, and cfb* + * by specifying a thin line bias to be applied to a particular screen + * using the following function. The bias parameter is an OR'ing of + * the appropriate OCTANT constants defined above to indicate which + * octants to bias a line to prefer an axial step when the Bresenham + * error term is exactly zero. The octants are mapped as follows: + * + * \ | / + * \ 3 | 2 / + * \ | / + * 4 \ | / 1 + * \|/ + * ----------- + * /|\ + * 5 / | \ 8 + * / | \ + * / 6 | 7 \ + * / | \ + * + * For more information, see "Ambiguities in Incremental Line Rastering," + * Jack E. Bresenham, IEEE CG&A, May 1987. + */ + +/* + * Private definitions needed for drawing thin (zero width) lines + * Used by the mi, mfb, and all cfb* components. + */ + +#define X_AXIS 0 +#define Y_AXIS 1 + +#define OUT_LEFT 0x08 +#define OUT_RIGHT 0x04 +#define OUT_ABOVE 0x02 +#define OUT_BELOW 0x01 + +#define OUTCODES(_result, _x, _y, _pbox) \ + if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \ + else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \ + if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \ + else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW; + +#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \ +{\ + if (x < xmin) outcode |= OUT_LEFT;\ + if (x > xmax) outcode |= OUT_RIGHT;\ + if (y < ymin) outcode |= OUT_ABOVE;\ + if (y > ymax) outcode |= OUT_BELOW;\ +} + +#define SWAPINT(i, j) \ +{ int _t = i; i = j; j = _t; } + +#define SWAPPT(i, j) \ +{ DDXPointRec _t; _t = i; i = j; j = _t; } + +#define SWAPINT_PAIR(x1, y1, x2, y2)\ +{ int t = x1; x1 = x2; x2 = t;\ + t = y1; y1 = y2; y2 = t;\ +} + +#define miGetZeroLineBias(_pScreen) (DEFAULTZEROLINEBIAS) + +#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \ + (_octant) = 0; \ + (_sx) = (_SX); \ + if (((_adx) = (_x2) - (_x1)) < 0) { \ + (_adx) = -(_adx); \ + (_sx = -(_sx)); \ + (_octant) |= XDECREASING; \ + } \ + (_sy) = (_SY); \ + if (((_ady) = (_y2) - (_y1)) < 0) { \ + (_ady) = -(_ady); \ + (_sy = -(_sy)); \ + (_octant) |= YDECREASING; \ + } + +#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR) + +#define FIXUP_ERROR(_e, _octant, _bias) \ + (_e) -= (((_bias) >> (_octant)) & 1) + +#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR)) +#define IsYMajorOctant(_octant) ((_octant) & YMAJOR) +#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING) +#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING) + +static int miZeroClipLine (int /*xmin */ , + int /*ymin */ , + int /*xmax */ , + int /*ymax */ , + int * /*new_x1 */ , + int * /*new_y1 */ , + int * /*new_x2 */ , + int * /*new_y2 */ , + unsigned int /*adx */ , + unsigned int /*ady */ , + int * /*pt1_clipped */ , + int * /*pt2_clipped */ , + int /*octant */ , + unsigned int /*bias */ , + int /*oc1 */ , + int /*oc2 */ + ); + +/* + * interface data to span-merging polygon filler + */ + +typedef struct _SpanData { + SpanGroup fgGroup, bgGroup; +} SpanDataRec, *SpanDataPtr; + +#define AppendSpanGroup(pGC, foreground, spanPtr, spanData) { \ + SpanGroup *group, *othergroup = NULL; \ + if (foreground) \ + { \ + group = &spanData->fgGroup; \ + if (pGC->lineStyle == LineDoubleDash) \ + othergroup = &spanData->bgGroup; \ + } \ + else \ + { \ + group = &spanData->bgGroup; \ + othergroup = &spanData->fgGroup; \ + } \ + miAppendSpans (group, othergroup, spanPtr); \ +} + +/* + * Polygon edge description for integer wide-line routines + */ + +typedef struct _PolyEdge { + int height; /* number of scanlines to process */ + int x; /* starting x coordinate */ + int stepx; /* fixed integral dx */ + int signdx; /* variable dx sign */ + int e; /* initial error term */ + int dy; + int dx; +} PolyEdgeRec, *PolyEdgePtr; + +#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */ + +/* + * types for general polygon routines + */ + +typedef struct _PolyVertex { + double x, y; +} PolyVertexRec, *PolyVertexPtr; + +typedef struct _PolySlope { + int dx, dy; + double k; /* x0 * dy - y0 * dx */ +} PolySlopeRec, *PolySlopePtr; + +/* + * Line face description for caps/joins + */ + +typedef struct _LineFace { + double xa, ya; + int dx, dy; + int x, y; + double k; +} LineFaceRec, *LineFacePtr; + +/* + * macros for polygon fillers + */ + +#define MIPOLYRELOADLEFT if (!left_height && left_count) { \ + left_height = left->height; \ + left_x = left->x; \ + left_stepx = left->stepx; \ + left_signdx = left->signdx; \ + left_e = left->e; \ + left_dy = left->dy; \ + left_dx = left->dx; \ + --left_count; \ + ++left; \ + } + +#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \ + right_height = right->height; \ + right_x = right->x; \ + right_stepx = right->stepx; \ + right_signdx = right->signdx; \ + right_e = right->e; \ + right_dy = right->dy; \ + right_dx = right->dx; \ + --right_count; \ + ++right; \ + } + +#define MIPOLYSTEPLEFT left_x += left_stepx; \ + left_e += left_dx; \ + if (left_e > 0) \ + { \ + left_x += left_signdx; \ + left_e -= left_dy; \ + } + +#define MIPOLYSTEPRIGHT right_x += right_stepx; \ + right_e += right_dx; \ + if (right_e > 0) \ + { \ + right_x += right_signdx; \ + right_e -= right_dy; \ + } + +static void miRoundJoinClip (LineFacePtr /*pLeft */ , + LineFacePtr /*pRight */ , + PolyEdgePtr /*edge1 */ , + PolyEdgePtr /*edge2 */ , + int * /*y1 */ , + int * /*y2 */ , + Boolean * /*left1 */ , + Boolean * /*left2 */ + ); + +static int miRoundCapClip (LineFacePtr /*face */ , + Boolean /*isInt */ , + PolyEdgePtr /*edge */ , + Boolean * /*leftEdge */ + ); + +static int miPolyBuildEdge (double x0, double y0, double k, int dx, int dy, + int xi, int yi, int left, PolyEdgePtr edge); +static int miPolyBuildPoly (PolyVertexPtr vertices, PolySlopePtr slopes, + int count, int xi, int yi, PolyEdgePtr left, + PolyEdgePtr right, int *pnleft, int *pnright, int *h); + + +static void +miStepDash (int dist, /* distance to step */ + int *pDashIndex, /* current dash */ + unsigned char *pDash, /* dash list */ + int numInDashList, /* total length of dash list */ + int *pDashOffset /* offset into current dash */ + ) +{ + int dashIndex, dashOffset; + int totallen; + int i; + + dashIndex = *pDashIndex; + dashOffset = *pDashOffset; + if (dist < pDash[dashIndex] - dashOffset) { + *pDashOffset = dashOffset + dist; + return; + } + dist -= pDash[dashIndex] - dashOffset; + if (++dashIndex == numInDashList) + dashIndex = 0; + totallen = 0; + for (i = 0; i < numInDashList; i++) + totallen += pDash[i]; + if (totallen > 0 && totallen <= dist) + dist = dist % totallen; + while (dist >= pDash[dashIndex]) { + dist -= pDash[dashIndex]; + if (++dashIndex == numInDashList) + dashIndex = 0; + } + *pDashIndex = dashIndex; + *pDashOffset = dist; +} + +/* + +These routines maintain lists of Spans, in order to implement the +``touch-each-pixel-once'' rules of wide lines and arcs. + +Written by Joel McCormack, Summer 1989. + +*/ + + +static void +miInitSpanGroup (SpanGroup * spanGroup) +{ + spanGroup->size = 0; + spanGroup->count = 0; + spanGroup->group = NULL; + spanGroup->ymin = MAX_COORDINATE; + spanGroup->ymax = MIN_COORDINATE; +} /* InitSpanGroup */ + +#define YMIN(spans) (spans->points[0].y) +#define YMAX(spans) (spans->points[spans->count-1].y) + +static void +miSubtractSpans (SpanGroup * spanGroup, Spans * sub) +{ + int i, subCount, spansCount; + int ymin, ymax, xmin, xmax; + Spans *spans; + DDXPointPtr subPt, spansPt; + int *subWid, *spansWid; + int extra; + + ymin = YMIN (sub); + ymax = YMAX (sub); + spans = spanGroup->group; + for (i = spanGroup->count; i; i--, spans++) { + if (YMIN (spans) <= ymax && ymin <= YMAX (spans)) { + subCount = sub->count; + subPt = sub->points; + subWid = sub->widths; + spansCount = spans->count; + spansPt = spans->points; + spansWid = spans->widths; + extra = 0; + for (;;) { + while (spansCount && spansPt->y < subPt->y) { + spansPt++; + spansWid++; + spansCount--; + } + if (!spansCount) + break; + while (subCount && subPt->y < spansPt->y) { + subPt++; + subWid++; + subCount--; + } + if (!subCount) + break; + if (subPt->y == spansPt->y) { + xmin = subPt->x; + xmax = xmin + *subWid; + if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) { + ; + } else if (xmin <= spansPt->x) { + if (xmax >= spansPt->x + *spansWid) { + memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); + memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); + spansPt--; + spansWid--; + spans->count--; + extra++; + } else { + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } else { + if (xmax >= spansPt->x + *spansWid) { + *spansWid = xmin - spansPt->x; + } else { + if (!extra) { + DDXPointPtr newPt; + int *newwid; + +#define EXTRA 8 + newPt = xrealloc (spans->points, + (spans->count + + EXTRA) * sizeof (DDXPointRec)); + if (!newPt) + break; + spansPt = newPt + (spansPt - spans->points); + spans->points = newPt; + newwid = xrealloc (spans->widths, + (spans->count + EXTRA) * sizeof (int)); + if (!newwid) + break; + spansWid = newwid + (spansWid - spans->widths); + spans->widths = newwid; + extra = EXTRA; + } + memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); + memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); + spans->count++; + extra--; + *spansWid = xmin - spansPt->x; + spansWid++; + spansPt++; + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } + } + spansPt++; + spansWid++; + spansCount--; + } + } + } +} + +static void +miAppendSpans (SpanGroup * spanGroup, SpanGroup * otherGroup, Spans * spans) +{ + int ymin, ymax; + int spansCount; + + spansCount = spans->count; + if (spansCount > 0) { + if (spanGroup->size == spanGroup->count) { + spanGroup->size = (spanGroup->size + 8) * 2; + spanGroup->group = + xrealloc (spanGroup->group, sizeof (Spans) * spanGroup->size); + } + + spanGroup->group[spanGroup->count] = *spans; + (spanGroup->count)++; + ymin = spans->points[0].y; + if (ymin < spanGroup->ymin) + spanGroup->ymin = ymin; + ymax = spans->points[spansCount - 1].y; + if (ymax > spanGroup->ymax) + spanGroup->ymax = ymax; + if (otherGroup && otherGroup->ymin < ymax && ymin < otherGroup->ymax) { + miSubtractSpans (otherGroup, spans); + } + } else { + xfree (spans->points); + xfree (spans->widths); + } +} /* AppendSpans */ + +static void +miFreeSpanGroup (SpanGroup * spanGroup) +{ + xfree (spanGroup->group); +} + +static void +QuickSortSpansX (DDXPointRec points[], int widths[], int numSpans) +{ + int x; + int i, j, m; + DDXPointPtr r; + +/* Always called with numSpans > 1 */ +/* Sorts only by x, as all y should be the same */ + +#define ExchangeSpans(a, b) \ +{ \ + DDXPointRec tpt; \ + int tw; \ + \ + tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + + do { + if (numSpans < 9) { + /* Do insertion sort */ + int xprev; + + xprev = points[0].x; + i = 1; + do { /* while i != numSpans */ + x = points[i].x; + if (xprev > x) { + /* points[i] is out of order. Move into proper location. */ + DDXPointRec tpt; + int tw, k; + + for (j = 0; x >= points[j].x; j++) { + } + tpt = points[i]; + tw = widths[i]; + for (k = i; k != j; k--) { + points[k] = points[k - 1]; + widths[k] = widths[k - 1]; + } + points[j] = tpt; + widths[j] = tw; + x = points[i].x; + } /* if out of order */ + xprev = x; + i++; + } while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (points[m].x > points[0].x) + ExchangeSpans (m, 0); + if (points[m].x > points[numSpans - 1].x) + ExchangeSpans (m, numSpans - 1); + if (points[m].x > points[0].x) + ExchangeSpans (m, 0); + x = points[0].x; + + /* Partition array */ + i = 0; + j = numSpans; + do { + r = &(points[i]); + do { + r++; + i++; + } while (i != numSpans && r->x < x); + r = &(points[j]); + do { + r--; + j--; + } while (x < r->x); + if (i < j) + ExchangeSpans (i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans (0, j); + + /* Recurse */ + if (numSpans - j - 1 > 1) + QuickSortSpansX (&points[j + 1], &widths[j + 1], numSpans - j - 1); + numSpans = j; + } while (numSpans > 1); +} /* QuickSortSpans */ + + +static int +UniquifySpansX (Spans * spans, DDXPointRec * newPoints, int *newWidths) +{ + int newx1, newx2, oldpt, i, y; + DDXPointRec *oldPoints; + int *oldWidths; + int *startNewWidths; + +/* Always called with numSpans > 1 */ +/* Uniquify the spans, and stash them into newPoints and newWidths. Return the + number of unique spans. */ + + + startNewWidths = newWidths; + + oldPoints = spans->points; + oldWidths = spans->widths; + + y = oldPoints->y; + newx1 = oldPoints->x; + newx2 = newx1 + *oldWidths; + + for (i = spans->count - 1; i != 0; i--) { + oldPoints++; + oldWidths++; + oldpt = oldPoints->x; + if (oldpt > newx2) { + /* Write current span, start a new one */ + newPoints->x = newx1; + newPoints->y = y; + *newWidths = newx2 - newx1; + newPoints++; + newWidths++; + newx1 = oldpt; + newx2 = oldpt + *oldWidths; + } else { + /* extend current span, if old extends beyond new */ + oldpt = oldpt + *oldWidths; + if (oldpt > newx2) + newx2 = oldpt; + } + } /* for */ + + /* Write final span */ + newPoints->x = newx1; + *newWidths = newx2 - newx1; + newPoints->y = y; + + return (newWidths - startNewWidths) + 1; +} /* UniquifySpansX */ + +static void +miDisposeSpanGroup (SpanGroup * spanGroup) +{ + int i; + Spans *spans; + + for (i = 0; i < spanGroup->count; i++) { + spans = spanGroup->group + i; + xfree (spans->points); + xfree (spans->widths); + } +} + +static void +miFillUniqueSpanGroup (GCPtr pGC, SpanGroup * spanGroup, Boolean foreground) +{ + int i; + Spans *spans; + Spans *yspans; + int *ysizes; + int ymin, ylength; + + /* Outgoing spans for one big call to FillSpans */ + DDXPointPtr points; + int *widths; + int count; + + if (spanGroup->count == 0) + return; + + if (spanGroup->count == 1) { + /* Already should be sorted, unique */ + spans = spanGroup->group; + (*pGC->ops->FillSpans) + (pGC, spans->count, spans->points, spans->widths, TRUE, foreground); + xfree (spans->points); + xfree (spans->widths); + } else { + /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ + /* This seems to be the fastest thing to do. I've tried sorting on + both x and y at the same time rather than creating into all those + y buckets, but it was somewhat slower. */ + + ymin = spanGroup->ymin; + ylength = spanGroup->ymax - ymin + 1; + + /* Allocate Spans for y buckets */ + yspans = (Spans*)xalloc (ylength * sizeof (Spans)); + ysizes = (int *)xalloc (ylength * sizeof (int)); + + if (!yspans || !ysizes) { + xfree (yspans); + xfree (ysizes); + miDisposeSpanGroup (spanGroup); + return; + } + + for (i = 0; i != ylength; i++) { + ysizes[i] = 0; + yspans[i].count = 0; + yspans[i].points = NULL; + yspans[i].widths = NULL; + } + + /* Go through every single span and put it into the correct bucket */ + count = 0; + for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) { + int index; + int j; + + for (j = 0, points = spans->points, widths = spans->widths; + j != spans->count; j++, points++, widths++) { + index = points->y - ymin; + if (index >= 0 && index < ylength) { + Spans *newspans = &(yspans[index]); + if (newspans->count == ysizes[index]) { + DDXPointPtr newpoints; + int *newwidths; + ysizes[index] = (ysizes[index] + 8) * 2; + newpoints = xrealloc (newspans->points, + ysizes[index] * sizeof (DDXPointRec)); + newwidths = xrealloc (newspans->widths, + ysizes[index] * sizeof (int)); + if (!newpoints || !newwidths) { + for (i = 0; i < ylength; i++) { + xfree (yspans[i].points); + xfree (yspans[i].widths); + } + xfree (yspans); + xfree (ysizes); + xfree (newpoints); + xfree (newwidths); + miDisposeSpanGroup (spanGroup); + return; + } + newspans->points = newpoints; + newspans->widths = newwidths; + } + newspans->points[newspans->count] = *points; + newspans->widths[newspans->count] = *widths; + (newspans->count)++; + } /* if y value of span in range */ + } /* for j through spans */ + count += spans->count; + xfree (spans->points); + spans->points = NULL; + xfree (spans->widths); + spans->widths = NULL; + } /* for i thorough Spans */ + + /* Now sort by x and uniquify each bucket into the final array */ + points = (DDXPointRec*)xalloc (count * sizeof (DDXPointRec)); + widths = (int *)xalloc (count * sizeof (int)); + if (!points || !widths) { + for (i = 0; i < ylength; i++) { + xfree (yspans[i].points); + xfree (yspans[i].widths); + } + xfree (yspans); + xfree (ysizes); + xfree (points); + xfree (widths); + return; + } + count = 0; + for (i = 0; i != ylength; i++) { + int ycount = yspans[i].count; + if (ycount > 0) { + if (ycount > 1) { + QuickSortSpansX (yspans[i].points, yspans[i].widths, ycount); + count += UniquifySpansX (&(yspans[i]), &(points[count]), &(widths[count])); + } else { + points[count] = yspans[i].points[0]; + widths[count] = yspans[i].widths[0]; + count++; + } + xfree (yspans[i].points); + xfree (yspans[i].widths); + } + } + + (*pGC->ops->FillSpans) (pGC, count, points, widths, TRUE, foreground); + xfree (points); + xfree (widths); + xfree (yspans); + xfree (ysizes); /* use (DE)xalloc for these? */ + } + + spanGroup->count = 0; + spanGroup->ymin = MAX_COORDINATE; + spanGroup->ymax = MIN_COORDINATE; +} + +/* + +The bresenham error equation used in the mi/mfb/cfb line routines is: + + e = error + dx = difference in raw X coordinates + dy = difference in raw Y coordinates + M = # of steps in X direction + N = # of steps in Y direction + B = 0 to prefer diagonal steps in a given octant, + 1 to prefer axial steps in a given octant + + For X major lines: + e = 2Mdy - 2Ndx - dx - B + -2dx <= e < 0 + + For Y major lines: + e = 2Ndx - 2Mdy - dy - B + -2dy <= e < 0 + +At the start of the line, we have taken 0 X steps and 0 Y steps, +so M = 0 and N = 0: + + X major e = 2Mdy - 2Ndx - dx - B + = -dx - B + + Y major e = 2Ndx - 2Mdy - dy - B + = -dy - B + +At the end of the line, we have taken dx X steps and dy Y steps, +so M = dx and N = dy: + + X major e = 2Mdy - 2Ndx - dx - B + = 2dxdy - 2dydx - dx - B + = -dx - B + Y major e = 2Ndx - 2Mdy - dy - B + = 2dydx - 2dxdy - dy - B + = -dy - B + +Thus, the error term is the same at the start and end of the line. + +Let us consider clipping an X coordinate. There are 4 cases which +represent the two independent cases of clipping the start vs. the +end of the line and an X major vs. a Y major line. In any of these +cases, we know the number of X steps (M) and we wish to find the +number of Y steps (N). Thus, we will solve our error term equation. +If we are clipping the start of the line, we will find the smallest +N that satisfies our error term inequality. If we are clipping the +end of the line, we will find the largest number of Y steps that +satisfies the inequality. In that case, since we are representing +the Y steps as (dy - N), we will actually want to solve for the +smallest N in that equation. + +Case 1: X major, starting X coordinate moved by M steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B + 2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx + N <= (2Mdy + dx - B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the > inequality to find the smallest: + + N = floor((2Mdy - dx - B) / 2dx) + 1 + = floor((2Mdy - dx - B + 2dx) / 2dx) + = floor((2Mdy + dx - B) / 2dx) + +Case 1b: X major, ending X coordinate moved to M steps + +Same derivations as Case 1, but we want the largest N that satisfies +the equations, so we use the <= inequality: + + N = floor((2Mdy + dx - B) / 2dx) + +Case 2: X major, ending X coordinate moved by M steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B + 2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx + N >= (2Mdy - dx + B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dx + B) / 2dx) + = floor((2Mdy - dx + B + 2dx - 1) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 2b: X major, starting X coordinate moved to M steps from end + +Same derivations as Case 2, but we want the smallest number of Y +steps, so we want the highest N, so we use the < inequality: + + N = ceiling((2Mdy + dx + B) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dx + B - 1) / 2dx) + +Case 3: Y major, starting X coordinate moved by M steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B + 2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx + N >= (2Mdy - dy + B) / 2dx + +Since we are trying to find the smallest N that satisfies these +equations, we should use the >= inequality to find the smallest: + + N = ceiling((2Mdy - dy + B) / 2dx) + = floor((2Mdy - dy + B + 2dx - 1) / 2dx) + = floor((2Mdy - dy + B - 1) / 2dx) + 1 + +Case 3b: Y major, ending X coordinate moved to M steps + +Same derivations as Case 3, but we want the largest N that satisfies +the equations, so we use the < inequality: + + N = ceiling((2Mdy + dy + B) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1 + = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx) + = floor((2Mdy + dy + B - 1) / 2dx) + +Case 4: Y major, ending X coordinate moved by M steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B + 2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx + N <= (2Mdy + dy - B) / 2dx + +Since we are trying to find the highest number of Y steps that +satisfies these equations, we need to find the smallest N, so +we should use the > inequality to find the smallest: + + N = floor((2Mdy - dy - B) / 2dx) + 1 + +Case 4b: Y major, starting X coordinate moved to M steps from end + +Same analysis as Case 4, but we want the smallest number of Y steps +which means the largest N, so we use the <= inequality: + + N = floor((2Mdy + dy - B) / 2dx) + +Now let's try the Y coordinates, we have the same 4 cases. + +Case 5: X major, starting Y coordinate moved by N steps + + -2dx <= 2Mdy - 2Ndx - dx - B < 0 + 2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B + 2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy + M >= (2Ndx - dx + B) / 2dy + +Since we are trying to find the smallest M, we use the >= inequality: + + M = ceiling((2Ndx - dx + B) / 2dy) + = floor((2Ndx - dx + B + 2dy - 1) / 2dy) + = floor((2Ndx - dx + B - 1) / 2dy) + 1 + +Case 5b: X major, ending Y coordinate moved to N steps + +Same derivations as Case 5, but we want the largest M that satisfies +the equations, so we use the < inequality: + + M = ceiling((2Ndx + dx + B) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dx + B - 1) / 2dy) + +Case 6: X major, ending Y coordinate moved by N steps + + -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 + -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 + -2dx <= 2Ndx - 2Mdy - dx - B < 0 + 2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B + 2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy + M <= (2Ndx + dx - B) / 2dy + +Largest # of X steps means smallest M, so use the > inequality: + + M = floor((2Ndx - dx - B) / 2dy) + 1 + +Case 6b: X major, starting Y coordinate moved to N steps from end + +Same derivations as Case 6, but we want the smallest # of X steps +which means the largest M, so use the <= inequality: + + M = floor((2Ndx + dx - B) / 2dy) + +Case 7: Y major, starting Y coordinate moved by N steps + + -2dy <= 2Ndx - 2Mdy - dy - B < 0 + 2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B + 2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy + M <= (2Ndx + dy - B) / 2dy + +To find the smallest M, use the > inequality: + + M = floor((2Ndx - dy - B) / 2dy) + 1 + = floor((2Ndx - dy - B + 2dy) / 2dy) + = floor((2Ndx + dy - B) / 2dy) + +Case 7b: Y major, ending Y coordinate moved to N steps + +Same derivations as Case 7, but we want the largest M that satisfies +the equations, so use the <= inequality: + + M = floor((2Ndx + dy - B) / 2dy) + +Case 8: Y major, ending Y coordinate moved by N steps + + -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 + -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 + -2dy <= 2Mdy - 2Ndx - dy - B < 0 + 2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B + 2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy + M >= (2Ndx - dy + B) / 2dy + +To find the highest X steps, find the smallest M, use the >= inequality: + + M = ceiling((2Ndx - dy + B) / 2dy) + = floor((2Ndx - dy + B + 2dy - 1) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +Case 8b: Y major, starting Y coordinate moved to N steps from the end + +Same derivations as Case 8, but we want to find the smallest # of X +steps which means the largest M, so we use the < inequality: + + M = ceiling((2Ndx + dy + B) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1 + = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy) + = floor((2Ndx + dy + B - 1) / 2dy) + +So, our equations are: + + 1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx) + 1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx) + 2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + 2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx) + + 3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1 + 3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx) + 4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1 + 4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx) + + 5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1 + 5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy) + 6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1 + 6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy) + + 7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy) + 7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy) + 8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + 8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy) + +We have the following constraints on all of the above terms: + + 0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine + 0 <= dx/dy <= 2^16 - 1 + 0 <= B <= 1 + +The floor in all of the above equations can be accomplished with a +simple C divide operation provided that both numerator and denominator +are positive. + +Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0 +and moving a Y coordinate implies dy != 0, we know that the denominators +are all > 0. + +For all lines, (-B) and (B-1) are both either 0 or -1, depending on the +bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1 +or > 0 to prove that the numerators are positive (or zero). + +For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the +constraints, the first four equations all have numerators >= 0. + +For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy +So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy +or (2Mdy + dy) > 0. So all of their numerators are >= 0. + +For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx) +>= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0. + +For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators +are > 0. + +To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This +is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1) + <= 2^16 * (2^16 - 1) + (2^16 - 1) + <= 2^32 - 2^16 + 2^16 - 1 + <= 2^32 - 1 +Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of +the numerator is therefore (2^32 - 1), which does not overflow an unsigned +32 bit variable. + +*/ + +/* Bit codes for the terms of the 16 clipping equations defined below. */ + +#define T_2NDX (1 << 0) +#define T_2MDY (0) /* implicit term */ +#define T_DXNOTY (1 << 1) +#define T_DYNOTX (0) /* implicit term */ +#define T_SUBDXORY (1 << 2) +#define T_ADDDX (T_DXNOTY) /* composite term */ +#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */ +#define T_ADDDY (T_DYNOTX) /* composite term */ +#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */ +#define T_BIASSUBONE (1 << 3) +#define T_SUBBIAS (0) /* implicit term */ +#define T_DIV2DX (1 << 4) +#define T_DIV2DY (0) /* implicit term */ +#define T_ADDONE (1 << 5) + +/* Bit masks defining the 16 equations used in miZeroClipLine. */ + +#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) +#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) +#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) + +#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE) +#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX) +#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE) +#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX) + +#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE) +#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY) +#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE) +#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY) + +#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) +#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) +#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) + +/* miZeroClipLine + * + * returns: 1 for partially clipped line + * -1 for completely clipped line + * + */ +static int +miZeroClipLine (int xmin, int ymin, int xmax, int ymax, + int *new_x1, int *new_y1, int *new_x2, int *new_y2, + unsigned int adx, unsigned int ady, + int *pt1_clipped, int *pt2_clipped, int octant, unsigned int bias, int oc1, int oc2) +{ + int swapped = 0; + int clipDone = 0; + CARD32 utmp = 0; + int clip1, clip2; + int x1, y1, x2, y2; + int x1_orig, y1_orig, x2_orig, y2_orig; + int xmajor; + int negslope = 0, anchorval = 0; + unsigned int eqn = 0; + + x1 = x1_orig = *new_x1; + y1 = y1_orig = *new_y1; + x2 = x2_orig = *new_x2; + y2 = y2_orig = *new_y2; + + clip1 = 0; + clip2 = 0; + + xmajor = IsXMajorOctant (octant); + bias = ((bias >> octant) & 1); + + while (1) { + if ((oc1 & oc2) != 0) { /* trivial reject */ + clipDone = -1; + clip1 = oc1; + clip2 = oc2; + break; + } else if ((oc1 | oc2) == 0) { /* trivial accept */ + clipDone = 1; + if (swapped) { + SWAPINT_PAIR (x1, y1, x2, y2); + SWAPINT (clip1, clip2); + } + break; + } else { /* have to clip */ + + /* only clip one point at a time */ + if (oc1 == 0) { + SWAPINT_PAIR (x1, y1, x2, y2); + SWAPINT_PAIR (x1_orig, y1_orig, x2_orig, y2_orig); + SWAPINT (oc1, oc2); + SWAPINT (clip1, clip2); + swapped = !swapped; + } + + clip1 |= oc1; + if (oc1 & OUT_LEFT) { + negslope = IsYDecreasingOctant (octant); + utmp = xmin - x1_orig; + if (utmp <= 32767) { /* clip based on near endpt */ + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } else { /* clip based on far endpt */ + + utmp = x2_orig - xmin; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmin; + } else if (oc1 & OUT_ABOVE) { + negslope = IsXDecreasingOctant (octant); + utmp = ymin - y1_orig; + if (utmp <= 32767) { /* clip based on near endpt */ + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } else { /* clip based on far endpt */ + + utmp = y2_orig - ymin; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymin; + } else if (oc1 & OUT_RIGHT) { + negslope = IsYDecreasingOctant (octant); + utmp = x1_orig - xmax; + if (utmp <= 32767) { /* clip based on near endpt */ + if (xmajor) + eqn = (swapped) ? EQN2 : EQN1; + else + eqn = (swapped) ? EQN4 : EQN3; + anchorval = y1_orig; + } else { /* clip based on far endpt */ + + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * to the right of a clip rectangle. + */ + utmp = xmax - x2_orig; + if (xmajor) + eqn = (swapped) ? EQN1B : EQN2B; + else + eqn = (swapped) ? EQN3B : EQN4B; + anchorval = y2_orig; + negslope = !negslope; + } + x1 = xmax; + } else if (oc1 & OUT_BELOW) { + negslope = IsXDecreasingOctant (octant); + utmp = y1_orig - ymax; + if (utmp <= 32767) { /* clip based on near endpt */ + if (xmajor) + eqn = (swapped) ? EQN6 : EQN5; + else + eqn = (swapped) ? EQN8 : EQN7; + anchorval = x1_orig; + } else { /* clip based on far endpt */ + + /* + * Technically since the equations can handle + * utmp == 32768, this overflow code isn't + * needed since X11 protocol can't generate + * a line which goes more than 32768 pixels + * below the bottom of a clip rectangle. + */ + utmp = ymax - y2_orig; + if (xmajor) + eqn = (swapped) ? EQN5B : EQN6B; + else + eqn = (swapped) ? EQN7B : EQN8B; + anchorval = x2_orig; + negslope = !negslope; + } + y1 = ymax; + } + + if (swapped) + negslope = !negslope; + + utmp <<= 1; /* utmp = 2N or 2M */ + if (eqn & T_2NDX) + utmp = (utmp * adx); + else /* (eqn & T_2MDY) */ + utmp = (utmp * ady); + if (eqn & T_DXNOTY) + if (eqn & T_SUBDXORY) + utmp -= adx; + else + utmp += adx; + else /* (eqn & T_DYNOTX) */ if (eqn & T_SUBDXORY) + utmp -= ady; + else + utmp += ady; + if (eqn & T_BIASSUBONE) + utmp += bias - 1; + else /* (eqn & T_SUBBIAS) */ + utmp -= bias; + if (eqn & T_DIV2DX) + utmp /= (adx << 1); + else /* (eqn & T_DIV2DY) */ + utmp /= (ady << 1); + if (eqn & T_ADDONE) + utmp++; + + if (negslope) + utmp = (uint32_t)(-(int32_t)utmp); + + if (eqn & T_2NDX) /* We are calculating X steps */ + x1 = anchorval + utmp; + else /* else, Y steps */ + y1 = anchorval + utmp; + + oc1 = 0; + MIOUTCODES (oc1, x1, y1, xmin, ymin, xmax, ymax); + } + } + + *new_x1 = x1; + *new_y1 = y1; + *new_x2 = x2; + *new_y2 = y2; + + *pt1_clipped = clip1; + *pt2_clipped = clip2; + + return clipDone; +} + +/* Draw lineSolid, fillStyle-independent zero width lines. + * + * Must keep X and Y coordinates in "ints" at least until after they're + * translated and clipped to accomodate CoordModePrevious lines with very + * large coordinates. + * + * Draws the same pixels regardless of sign(dx) or sign(dy). + * + * Ken Whaley + * + */ + +#define MI_OUTPUT_POINT(xx, yy)\ +{\ + if ( !new_span && yy == current_y)\ + {\ + if (xx < spans->x)\ + spans->x = xx;\ + ++*widths;\ + }\ + else\ + {\ + ++Nspans;\ + ++spans;\ + ++widths;\ + spans->x = xx;\ + spans->y = yy;\ + *widths = 1;\ + current_y = yy;\ + new_span = FALSE;\ + }\ +} + +void +miZeroLine (GCPtr pGC, int mode, /* Origin or Previous */ + int npt, /* number of points */ + DDXPointPtr pptInit) +{ + int Nspans, current_y = 0; + DDXPointPtr ppt; + DDXPointPtr pspanInit, spans; + int *pwidthInit, *widths, list_len; + int xleft, ytop, xright, ybottom; + int new_x1, new_y1, new_x2, new_y2; + int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; + int oc1, oc2; + int result; + int pt1_clipped, pt2_clipped = 0; + Boolean new_span; + int signdx, signdy; + int clipdx, clipdy; + int width, height; + int adx, ady; + int octant; + unsigned int bias = miGetZeroLineBias (screen); + int e, e1, e2, e3; /* Bresenham error terms */ + int length; /* length of lines == # of pixels on major axis */ + + xleft = 0; + ytop = 0; + xright = pGC->width - 1; + ybottom = pGC->height - 1; + + /* it doesn't matter whether we're in drawable or screen coordinates, + * FillSpans simply cannot take starting coordinates outside of the + * range of a DDXPointRec component. + */ + if (xright > MAX_COORDINATE) + xright = MAX_COORDINATE; + if (ybottom > MAX_COORDINATE) + ybottom = MAX_COORDINATE; + + /* since we're clipping to the drawable's boundaries & coordinate + * space boundaries, we're guaranteed that the larger of width/height + * is the longest span we'll need to output + */ + width = xright - xleft + 1; + height = ybottom - ytop + 1; + list_len = (height >= width) ? height : width; + pspanInit = (DDXPointRec *)xalloc (list_len * sizeof (DDXPointRec)); + pwidthInit = (int *)xalloc (list_len * sizeof (int)); + if (!pspanInit || !pwidthInit) + goto out; + + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + ppt = pptInit; + + xstart = ppt->x; + ystart = ppt->y; + + /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify + * iteration logic + */ + x2 = xstart; + y2 = ystart; + oc2 = 0; + MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom); + + while (--npt > 0) { + if (Nspans > 0) + (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE); + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + + x1 = x2; + y1 = y2; + oc1 = oc2; + ++ppt; + + x2 = ppt->x; + y2 = ppt->y; + if (mode == CoordModePrevious) { + x2 += x1; + y2 += y1; + } + + oc2 = 0; + MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom); + + CalcLineDeltas (x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) { + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + length = adx; /* don't draw endpoint in main loop */ + + FIXUP_ERROR (e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) { + result = miZeroClipLine (xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs (new_x2 - new_x1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) { + /* must calculate new error terms */ + clipdx = abs (new_x1 - x1); + clipdy = abs (new_y1 - y1); + e += (clipdy * e2) + ((clipdx - clipdy) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) { + MI_OUTPUT_POINT (x, y); + e += e1; + if (e >= 0) { + y += signdy; + e += e3; + } + x += signdx; + } + } else { /* Y major line */ + + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + length = ady; /* don't draw endpoint in main loop */ + + SetYMajorOctant (octant); + FIXUP_ERROR (e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) { + result = miZeroClipLine (xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs (new_y2 - new_y1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) { + /* must calculate new error terms */ + clipdx = abs (new_x1 - x1); + clipdy = abs (new_y1 - y1); + e += (clipdx * e2) + ((clipdy - clipdx) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) { + MI_OUTPUT_POINT (x, y); + e += e1; + if (e >= 0) { + x += signdx; + e += e3; + } + y += signdy; + } + } + } + + /* only do the capnotlast check on the last segment + * and only if the endpoint wasn't clipped. And then, if the last + * point is the same as the first point, do not draw it, unless the + * line is degenerate + */ + if ((!pt2_clipped) && (pGC->capStyle != CapNotLast) && + (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) { + MI_OUTPUT_POINT (x, y); + } + + if (Nspans > 0) + (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE); + +out: + xfree (pwidthInit); + xfree (pspanInit); +} + +void +miZeroDashLine (GCPtr pgc, int mode, int nptInit, /* number of points in polyline */ + DDXPointRec * pptInit /* points in the polyline */ + ) +{ + /* XXX kludge until real zero-width dash code is written */ + pgc->lineWidth = 1; + miWideDash (pgc, mode, nptInit, pptInit); + pgc->lineWidth = 0; +} + +static void miLineArc (GCPtr pGC, + Boolean foreground, SpanDataPtr spanData, + LineFacePtr leftFace, + LineFacePtr rightFace, double xorg, double yorg, Boolean isInt); + + +/* + * spans-based polygon filler + */ + +static void +miFillPolyHelper (GCPtr pGC, Boolean foreground, + SpanDataPtr spanData, int y, int overall_height, + PolyEdgePtr left, PolyEdgePtr right, int left_count, int right_count) +{ + int left_x = 0, left_e = 0; + int left_stepx = 0; + int left_signdx = 0; + int left_dy = 0, left_dx = 0; + + int right_x = 0, right_e = 0; + int right_stepx = 0; + int right_signdx = 0; + int right_dy = 0, right_dx = 0; + + int height = 0; + int left_height = 0, right_height = 0; + + DDXPointPtr ppt; + DDXPointPtr pptInit = NULL; + int *pwidth; + int *pwidthInit = NULL; + int xorg; + Spans spanRec; + + left_height = 0; + right_height = 0; + + if (!spanData) { + pptInit = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt)); + if (!pptInit) + return; + pwidthInit = (int *)xalloc (overall_height * sizeof (*pwidth)); + if (!pwidthInit) { + xfree (pptInit); + return; + } + ppt = pptInit; + pwidth = pwidthInit; + } else { + spanRec.points = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt)); + if (!spanRec.points) + return; + spanRec.widths = (int *)xalloc (overall_height * sizeof (int)); + if (!spanRec.widths) { + xfree (spanRec.points); + return; + } + ppt = spanRec.points; + pwidth = spanRec.widths; + } + + xorg = 0; + while ((left_count || left_height) && (right_count || right_height)) { + MIPOLYRELOADLEFT MIPOLYRELOADRIGHT height = left_height; + if (height > right_height) + height = right_height; + + left_height -= height; + right_height -= height; + + while (--height >= 0) { + if (right_x >= left_x) { + ppt->y = y; + ppt->x = left_x + xorg; + ppt++; + *pwidth++ = right_x - left_x + 1; + } + y++; + + MIPOLYSTEPLEFT MIPOLYSTEPRIGHT} + } + if (!spanData) { + (*pGC->ops->FillSpans) (pGC, ppt - pptInit, pptInit, pwidthInit, TRUE, foreground); + xfree (pwidthInit); + xfree (pptInit); + } else { + spanRec.count = ppt - spanRec.points; + AppendSpanGroup (pGC, foreground, &spanRec, spanData) + } +} + +static void +miFillRectPolyHelper (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, int x, int y, int w, int h) +{ + DDXPointPtr ppt; + int *pwidth; + Spans spanRec; + xRectangle rect; + + if (!spanData) { + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + (*pGC->ops->FillRects) (pGC, 1, &rect, foreground); + } else { + spanRec.points = (DDXPointRec *)xalloc (h * sizeof (*ppt)); + if (!spanRec.points) + return; + spanRec.widths = (int *)xalloc (h * sizeof (int)); + if (!spanRec.widths) { + xfree (spanRec.points); + return; + } + ppt = spanRec.points; + pwidth = spanRec.widths; + + while (h--) { + ppt->x = x; + ppt->y = y; + ppt++; + *pwidth++ = w; + y++; + } + spanRec.count = ppt - spanRec.points; + AppendSpanGroup (pGC, foreground, &spanRec, spanData) + } +} + +static int +miPolyBuildEdge (SPICE_GNUC_UNUSED double x0, double y0, double k, /* x0 * dy - y0 * dx */ + int dx, int dy, int xi, int yi, int left, PolyEdgePtr edge) +{ + int x, y, e; + int xady; + + if (dy < 0) { + dy = -dy; + dx = -dx; + k = -k; + } + y = ICEIL (y0); + xady = ICEIL (k) + y * dx; + + if (xady <= 0) + x = -(-xady / dy) - 1; + else + x = (xady - 1) / dy; + + e = xady - x * dy; + + if (dx >= 0) { + edge->signdx = 1; + edge->stepx = dx / dy; + edge->dx = dx % dy; + } else { + edge->signdx = -1; + edge->stepx = -(-dx / dy); + edge->dx = -dx % dy; + e = dy - e + 1; + } + edge->dy = dy; + edge->x = x + left + xi; + edge->e = e - dy; /* bias to compare against 0 instead of dy */ + return y + yi; +} + +#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) + +static int +miPolyBuildPoly (PolyVertexPtr vertices, + PolySlopePtr slopes, + int count, + int xi, + int yi, PolyEdgePtr left, PolyEdgePtr right, int *pnleft, int *pnright, int *h) +{ + int top, bottom; + double miny, maxy; + int i; + int j; + int clockwise; + int slopeoff; + int s; + int nright, nleft; + int y, lasty = 0, bottomy, topy = 0; + + /* find the top of the polygon */ + maxy = miny = vertices[0].y; + bottom = top = 0; + for (i = 1; i < count; i++) { + if (vertices[i].y < miny) { + top = i; + miny = vertices[i].y; + } + if (vertices[i].y >= maxy) { + bottom = i; + maxy = vertices[i].y; + } + } + clockwise = 1; + slopeoff = 0; + + i = top; + j = StepAround (top, -1, count); + + if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) { + clockwise = -1; + slopeoff = -1; + } + + bottomy = ICEIL (maxy) + yi; + + nright = 0; + + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) { + if (slopes[s].dy != 0) { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + slopes[s].k, + slopes[s].dx, slopes[s].dy, xi, yi, 0, &right[nright]); + if (nright != 0) + right[nright - 1].height = y - lasty; + else + topy = y; + nright++; + lasty = y; + } + + i = StepAround (i, clockwise, count); + s = StepAround (s, clockwise, count); + } + if (nright != 0) + right[nright - 1].height = bottomy - lasty; + + if (slopeoff == 0) + slopeoff = -1; + else + slopeoff = 0; + + nleft = 0; + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) { + if (slopes[s].dy != 0) { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + slopes[s].k, slopes[s].dx, slopes[s].dy, xi, yi, 1, &left[nleft]); + + if (nleft != 0) + left[nleft - 1].height = y - lasty; + nleft++; + lasty = y; + } + i = StepAround (i, -clockwise, count); + s = StepAround (s, -clockwise, count); + } + if (nleft != 0) + left[nleft - 1].height = bottomy - lasty; + *pnleft = nleft; + *pnright = nright; + *h = bottomy - topy; + return topy; +} + +static void +miLineOnePoint (GCPtr pGC, + Boolean foreground, + SPICE_GNUC_UNUSED SpanDataPtr spanData, + int x, + int y) +{ + DDXPointRec pt; + int wid; + + wid = 1; + pt.x = x; + pt.y = y; + (*pGC->ops->FillSpans) (pGC, 1, &pt, &wid, TRUE, foreground); +} + +static void +miLineJoin (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, LineFacePtr pLeft, LineFacePtr pRight) +{ + double mx = 0, my = 0; + double denom = 0.0; + PolyVertexRec vertices[4]; + PolySlopeRec slopes[4]; + int edgecount; + PolyEdgeRec left[4], right[4]; + int nleft, nright; + int y, height; + int swapslopes; + int joinStyle = pGC->joinStyle; + int lw = pGC->lineWidth; + + if (lw == 1 && !spanData) { + /* See if one of the lines will draw the joining pixel */ + if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) + return; + if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) + return; + if (joinStyle != JoinRound) { + denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; + if (denom == 0) + return; /* no join to draw */ + } + if (joinStyle != JoinMiter) { + miLineOnePoint (pGC, foreground, spanData, pLeft->x, pLeft->y); + return; + } + } else { + if (joinStyle == JoinRound) { + miLineArc (pGC, foreground, spanData, pLeft, pRight, (double) 0.0, (double) 0.0, TRUE); + return; + } + denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; + if (denom == 0.0) + return; /* no join to draw */ + } + + swapslopes = 0; + if (denom > 0) { + pLeft->xa = -pLeft->xa; + pLeft->ya = -pLeft->ya; + pLeft->dx = -pLeft->dx; + pLeft->dy = -pLeft->dy; + } else { + swapslopes = 1; + pRight->xa = -pRight->xa; + pRight->ya = -pRight->ya; + pRight->dx = -pRight->dx; + pRight->dy = -pRight->dy; + } + + vertices[0].x = pRight->xa; + vertices[0].y = pRight->ya; + slopes[0].dx = -pRight->dy; + slopes[0].dy = pRight->dx; + slopes[0].k = 0; + + vertices[1].x = 0; + vertices[1].y = 0; + slopes[1].dx = pLeft->dy; + slopes[1].dy = -pLeft->dx; + slopes[1].k = 0; + + vertices[2].x = pLeft->xa; + vertices[2].y = pLeft->ya; + + if (joinStyle == JoinMiter) { + my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - + pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx)) / denom; + if (pLeft->dy != 0) { + mx = pLeft->xa + (my - pLeft->ya) * (double) pLeft->dx / (double) pLeft->dy; + } else { + mx = pRight->xa + (my - pRight->ya) * (double) pRight->dx / (double) pRight->dy; + } + /* check miter limit */ + if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) + joinStyle = JoinBevel; + } + + if (joinStyle == JoinMiter) { + slopes[2].dx = pLeft->dx; + slopes[2].dy = pLeft->dy; + slopes[2].k = pLeft->k; + if (swapslopes) { + slopes[2].dx = -slopes[2].dx; + slopes[2].dy = -slopes[2].dy; + slopes[2].k = -slopes[2].k; + } + vertices[3].x = mx; + vertices[3].y = my; + slopes[3].dx = pRight->dx; + slopes[3].dy = pRight->dy; + slopes[3].k = pRight->k; + if (swapslopes) { + slopes[3].dx = -slopes[3].dx; + slopes[3].dy = -slopes[3].dy; + slopes[3].k = -slopes[3].k; + } + edgecount = 4; + } else { + double scale, dx, dy, adx, ady; + + adx = dx = pRight->xa - pLeft->xa; + ady = dy = pRight->ya - pLeft->ya; + if (adx < 0) + adx = -adx; + if (ady < 0) + ady = -ady; + scale = ady; + if (adx > ady) + scale = adx; + slopes[2].dx = (int) ((dx * 65536) / scale); + slopes[2].dy = (int) ((dy * 65536) / scale); + slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - + (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; + edgecount = 3; + } + + y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, + left, right, &nleft, &nright, &height); + miFillPolyHelper (pGC, foreground, spanData, y, height, left, right, nleft, nright); +} + +static int +miLineArcI (GCPtr pGC, int xorg, int yorg, DDXPointPtr points, int *widths) +{ + DDXPointPtr tpts, bpts; + int *twids, *bwids; + int x, y, e, ex, slw; + + tpts = points; + twids = widths; + slw = pGC->lineWidth; + if (slw == 1) { + tpts->x = xorg; + tpts->y = yorg; + *twids = 1; + return 1; + } + bpts = tpts + slw; + bwids = twids + slw; + y = (slw >> 1) + 1; + if (slw & 1) + e = -((y << 2) + 3); + else + e = -(y << 3); + ex = -4; + x = 0; + while (y) { + e += (y << 3) - 4; + while (e >= 0) { + x++; + e += (ex = -((x << 3) + 4)); + } + y--; + slw = (x << 1) + 1; + if ((e == ex) && (slw > 1)) + slw--; + tpts->x = xorg - x; + tpts->y = yorg - y; + tpts++; + *twids++ = slw; + if ((y != 0) && ((slw > 1) || (e != ex))) { + bpts--; + bpts->x = xorg - x; + bpts->y = yorg + y; + *--bwids = slw; + } + } + return (pGC->lineWidth); +} + +#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ + if (ybase == edgey) \ + { \ + if (edgeleft) \ + { \ + if (edge->x > xcl) \ + xcl = edge->x; \ + } \ + else \ + { \ + if (edge->x < xcr) \ + xcr = edge->x; \ + } \ + edgey++; \ + edge->x += edge->stepx; \ + edge->e += edge->dx; \ + if (edge->e > 0) \ + { \ + edge->x += edge->signdx; \ + edge->e -= edge->dy; \ + } \ + } + +static int +miLineArcD (GCPtr pGC, + double xorg, + double yorg, + DDXPointPtr points, + int *widths, + PolyEdgePtr edge1, + int edgey1, Boolean edgeleft1, PolyEdgePtr edge2, int edgey2, Boolean edgeleft2) +{ + DDXPointPtr pts; + int *wids; + double radius, x0, y0, el, er, yk, xlk, xrk, k; + int xbase, ybase, y, boty, xl, xr, xcl, xcr; + int ymin, ymax; + Boolean edge1IsMin, edge2IsMin; + int ymin1, ymin2; + + pts = points; + wids = widths; + xbase = (int)floor (xorg); + x0 = xorg - xbase; + ybase = ICEIL (yorg); + y0 = yorg - ybase; + xlk = x0 + x0 + 1.0; + xrk = x0 + x0 - 1.0; + yk = y0 + y0 - 1.0; + radius = ((double) pGC->lineWidth) / 2.0; + y = (int)floor (radius - y0 + 1.0); + ybase -= y; + ymin = ybase; + ymax = 65536; + edge1IsMin = FALSE; + ymin1 = edgey1; + if (edge1->dy >= 0) { + if (!edge1->dy) { + if (edgeleft1) + edge1IsMin = TRUE; + else + ymax = edgey1; + edgey1 = 65536; + } else { + if ((edge1->signdx < 0) == edgeleft1) + edge1IsMin = TRUE; + } + } + edge2IsMin = FALSE; + ymin2 = edgey2; + if (edge2->dy >= 0) { + if (!edge2->dy) { + if (edgeleft2) + edge2IsMin = TRUE; + else + ymax = edgey2; + edgey2 = 65536; + } else { + if ((edge2->signdx < 0) == edgeleft2) + edge2IsMin = TRUE; + } + } + if (edge1IsMin) { + ymin = ymin1; + if (edge2IsMin && ymin1 > ymin2) + ymin = ymin2; + } else if (edge2IsMin) + ymin = ymin2; + el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); + er = el + xrk; + xl = 1; + xr = 0; + if (x0 < 0.5) { + xl = 0; + el -= xlk; + } + boty = (y0 < -0.5) ? 1 : 0; + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) { + k = (y << 1) + yk; + er += k; + while (er > 0.0) { + xr++; + er += xrk - (xr << 1); + } + el += k; + while (el >= 0.0) { + xl--; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE (edgey1, edge1, edgeleft1); + CLIPSTEPEDGE (edgey2, edge2, edgeleft2); + if (xcr >= xcl) { + pts->x = xcl; + pts->y = ybase; + pts++; + *wids++ = xcr - xcl + 1; + } + } + er = xrk - (xr << 1) - er; + el = (xl << 1) - xlk - el; + boty = (int)floor (-y0 - radius + 1.0); + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) { + k = (y << 1) + yk; + er -= k; + while ((er >= 0.0) && (xr >= 0)) { + xr--; + er += xrk - (xr << 1); + } + el -= k; + while ((el > 0.0) && (xl <= 0)) { + xl++; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE (edgey1, edge1, edgeleft1); + CLIPSTEPEDGE (edgey2, edge2, edgeleft2); + if (xcr >= xcl) { + pts->x = xcl; + pts->y = ybase; + pts++; + *wids++ = xcr - xcl + 1; + } + } + return (pts - points); +} + +static int +miRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Boolean * leftEdge) +{ + int y; + int dx, dy; + double xa, ya; + Boolean left; + + dx = -face->dy; + dy = face->dx; + xa = face->xa; + ya = face->ya; + left = 1; + if (ya > 0) { + ya = 0.0; + xa = 0.0; + } + if (dy < 0 || (dy == 0 && dx > 0)) { + dx = -dx; + dy = -dy; + left = !left; + } + if (dx == 0 && dy == 0) + dy = 1; + if (dy == 0) { + y = ICEIL (face->ya) + face->y; + edge->x = -32767; + edge->stepx = 0; + edge->signdx = 0; + edge->e = -1; + edge->dy = 0; + edge->dx = 0; + edge->height = 0; + } else { + y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); + edge->height = 32767; + } + *leftEdge = !left; + return y; +} + +static void +miRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight, + PolyEdgePtr edge1, PolyEdgePtr edge2, int *y1, int *y2, Boolean * left1, Boolean * left2) +{ + double denom; + + denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; + + if (denom >= 0) { + pLeft->xa = -pLeft->xa; + pLeft->ya = -pLeft->ya; + } else { + pRight->xa = -pRight->xa; + pRight->ya = -pRight->ya; + } + *y1 = miRoundJoinFace (pLeft, edge1, left1); + *y2 = miRoundJoinFace (pRight, edge2, left2); +} + +static int +miRoundCapClip (LineFacePtr face, Boolean isInt, PolyEdgePtr edge, Boolean * leftEdge) +{ + int y; + int dx, dy; + double xa, ya, k; + Boolean left; + + dx = -face->dy; + dy = face->dx; + xa = face->xa; + ya = face->ya; + k = 0.0; + if (!isInt) + k = face->k; + left = 1; + if (dy < 0 || (dy == 0 && dx > 0)) { + dx = -dx; + dy = -dy; + xa = -xa; + ya = -ya; + left = !left; + } + if (dx == 0 && dy == 0) + dy = 1; + if (dy == 0) { + y = ICEIL (face->ya) + face->y; + edge->x = -32767; + edge->stepx = 0; + edge->signdx = 0; + edge->e = -1; + edge->dy = 0; + edge->dx = 0; + edge->height = 0; + } else { + y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); + edge->height = 32767; + } + *leftEdge = !left; + return y; +} + +static void +miLineArc (GCPtr pGC, + Boolean foreground, + SpanDataPtr spanData, + LineFacePtr leftFace, LineFacePtr rightFace, double xorg, double yorg, Boolean isInt) +{ + DDXPointPtr points; + int *widths; + int xorgi = 0, yorgi = 0; + Spans spanRec; + int n; + PolyEdgeRec edge1, edge2; + int edgey1, edgey2; + Boolean edgeleft1, edgeleft2; + + if (isInt) { + xorgi = leftFace ? leftFace->x : rightFace->x; + yorgi = leftFace ? leftFace->y : rightFace->y; + } + edgey1 = 65536; + edgey2 = 65536; + edge1.x = 0; /* not used, keep memory checkers happy */ + edge1.dy = -1; + edge2.x = 0; /* not used, keep memory checkers happy */ + edge2.dy = -1; + edgeleft1 = FALSE; + edgeleft2 = FALSE; + if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && + ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || + (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) { + if (isInt) { + xorg = (double) xorgi; + yorg = (double) yorgi; + } + if (leftFace && rightFace) { + miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, + &edgey1, &edgey2, &edgeleft1, &edgeleft2); + } else if (leftFace) { + edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); + } else if (rightFace) { + edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); + } + isInt = FALSE; + } + if (!spanData) { + points = (DDXPointRec *)xalloc (sizeof (DDXPointRec) * pGC->lineWidth); + if (!points) + return; + widths = (int *)xalloc (sizeof (int) * pGC->lineWidth); + if (!widths) { + xfree (points); + return; + } + } else { + points = (DDXPointRec *)xalloc (pGC->lineWidth * sizeof (DDXPointRec)); + if (!points) + return; + widths = (int *)xalloc (pGC->lineWidth * sizeof (int)); + if (!widths) { + xfree (points); + return; + } + spanRec.points = points; + spanRec.widths = widths; + } + if (isInt) + n = miLineArcI (pGC, xorgi, yorgi, points, widths); + else + n = miLineArcD (pGC, xorg, yorg, points, widths, + &edge1, edgey1, edgeleft1, &edge2, edgey2, edgeleft2); + + if (!spanData) { + (*pGC->ops->FillSpans) (pGC, n, points, widths, TRUE, foreground); + xfree (widths); + xfree (points); + } else { + spanRec.count = n; + AppendSpanGroup (pGC, foreground, &spanRec, spanData) + } +} + +static void +miLineProjectingCap (GCPtr pGC, + Boolean foreground, + SpanDataPtr spanData, + LineFacePtr face, + Boolean isLeft, + SPICE_GNUC_UNUSED double xorg, + SPICE_GNUC_UNUSED double yorg, + Boolean isInt) +{ + int xorgi = 0, yorgi = 0; + int lw; + PolyEdgeRec lefts[4], rights[4]; + int lefty, righty, topy, bottomy; + PolyEdgePtr left, right; + PolyEdgePtr top, bottom; + double xa, ya; + double k; + double xap, yap; + int dx, dy; + double projectXoff, projectYoff; + double maxy; + int finaly; + + if (isInt) { + xorgi = face->x; + yorgi = face->y; + } + lw = pGC->lineWidth; + dx = face->dx; + dy = face->dy; + k = face->k; + if (dy == 0) { + lefts[0].height = lw; + lefts[0].x = xorgi; + if (isLeft) + lefts[0].x -= (lw >> 1); + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = -lw; + lefts[0].dx = 0; + lefts[0].dy = lw; + rights[0].height = lw; + rights[0].x = xorgi; + if (!isLeft) + rights[0].x += ((lw + 1) >> 1); + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = -lw; + rights[0].dx = 0; + rights[0].dy = lw; + miFillPolyHelper (pGC, foreground, spanData, yorgi - (lw >> 1), lw, lefts, rights, 1, 1); + } else if (dx == 0) { + if (dy < 0) { + dy = -dy; + isLeft = !isLeft; + } + topy = yorgi; + bottomy = yorgi + dy; + if (isLeft) + topy -= (lw >> 1); + else + bottomy += (lw >> 1); + lefts[0].height = bottomy - topy; + lefts[0].x = xorgi - (lw >> 1); + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = -dy; + lefts[0].dx = dx; + lefts[0].dy = dy; + + rights[0].height = bottomy - topy; + rights[0].x = lefts[0].x + (lw - 1); + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = -dy; + rights[0].dx = dx; + rights[0].dy = dy; + miFillPolyHelper (pGC, foreground, spanData, topy, bottomy - topy, lefts, rights, 1, 1); + } else { + xa = face->xa; + ya = face->ya; + projectXoff = -ya; + projectYoff = xa; + if (dx < 0) { + right = &rights[1]; + left = &lefts[0]; + top = &rights[0]; + bottom = &lefts[1]; + } else { + right = &rights[0]; + left = &lefts[1]; + top = &lefts[0]; + bottom = &rights[1]; + } + if (isLeft) { + righty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 0, right); + + xa = -xa; + ya = -ya; + k = -k; + lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, xorgi, yorgi, 1, left); + if (dx > 0) { + ya = -ya; + xa = -xa; + } + xap = xa - projectXoff; + yap = ya - projectYoff; + topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, xorgi, yorgi, dx > 0, top); + bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); + maxy = -ya; + } else { + righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, xorgi, yorgi, 0, right); + + xa = -xa; + ya = -ya; + k = -k; + lefty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 1, left); + if (dx > 0) { + ya = -ya; + xa = -xa; + } + xap = xa - projectXoff; + yap = ya - projectYoff; + topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); + bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, xorgi, xorgi, dx < 0, bottom); + maxy = -ya + projectYoff; + } + finaly = ICEIL (maxy) + yorgi; + if (dx < 0) { + left->height = bottomy - lefty; + right->height = finaly - righty; + top->height = righty - topy; + } else { + right->height = bottomy - righty; + left->height = finaly - lefty; + top->height = lefty - topy; + } + bottom->height = finaly - bottomy; + miFillPolyHelper (pGC, foreground, spanData, topy, + bottom->height + bottomy - topy, lefts, rights, 2, 2); + } +} + +static void +miWideSegment (GCPtr pGC, + Boolean foreground, + SpanDataPtr spanData, + int x1, + int y1, + int x2, + int y2, + Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace) +{ + double l, L, r; + double xa, ya; + double projectXoff = 0.0, projectYoff = 0.0; + double k; + double maxy; + int x, y; + int dx, dy; + int finaly; + PolyEdgePtr left, right; + PolyEdgePtr top, bottom; + int lefty, righty, topy, bottomy; + int signdx; + PolyEdgeRec lefts[4], rights[4]; + LineFacePtr tface; + int lw = pGC->lineWidth; + + /* draw top-to-bottom always */ + if (y2 < y1 || (y2 == y1 && x2 < x1)) { + x = x1; + x1 = x2; + x2 = x; + + y = y1; + y1 = y2; + y2 = y; + + x = projectLeft; + projectLeft = projectRight; + projectRight = x; + + tface = leftFace; + leftFace = rightFace; + rightFace = tface; + } + + dy = y2 - y1; + signdx = 1; + dx = x2 - x1; + if (dx < 0) + signdx = -1; + + leftFace->x = x1; + leftFace->y = y1; + leftFace->dx = dx; + leftFace->dy = dy; + + rightFace->x = x2; + rightFace->y = y2; + rightFace->dx = -dx; + rightFace->dy = -dy; + + if (dy == 0) { + rightFace->xa = 0; + rightFace->ya = (double) lw / 2.0; + rightFace->k = -(double) (lw * dx) / 2.0; + leftFace->xa = 0; + leftFace->ya = -rightFace->ya; + leftFace->k = rightFace->k; + x = x1; + if (projectLeft) + x -= (lw >> 1); + y = y1 - (lw >> 1); + dx = x2 - x; + if (projectRight) + dx += ((lw + 1) >> 1); + dy = lw; + miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy); + } else if (dx == 0) { + leftFace->xa = (double) lw / 2.0; + leftFace->ya = 0; + leftFace->k = (double) (lw * dy) / 2.0; + rightFace->xa = -leftFace->xa; + rightFace->ya = 0; + rightFace->k = leftFace->k; + y = y1; + if (projectLeft) + y -= lw >> 1; + x = x1 - (lw >> 1); + dy = y2 - y; + if (projectRight) + dy += ((lw + 1) >> 1); + dx = lw; + miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy); + } else { + l = ((double) lw) / 2.0; + L = hypot ((double) dx, (double) dy); + + if (dx < 0) { + right = &rights[1]; + left = &lefts[0]; + top = &rights[0]; + bottom = &lefts[1]; + } else { + right = &rights[0]; + left = &lefts[1]; + top = &lefts[0]; + bottom = &rights[1]; + } + r = l / L; + + /* coord of upper bound at integral y */ + ya = -r * dx; + xa = r * dy; + + if (projectLeft | projectRight) { + projectXoff = -ya; + projectYoff = xa; + } + + /* xa * dy - ya * dx */ + k = l * L; + + leftFace->xa = xa; + leftFace->ya = ya; + leftFace->k = k; + rightFace->xa = -xa; + rightFace->ya = -ya; + rightFace->k = k; + + if (projectLeft) + righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 0, right); + else + righty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 0, right); + + /* coord of lower bound at integral y */ + ya = -ya; + xa = -xa; + + /* xa * dy - ya * dx */ + k = -k; + + if (projectLeft) + lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 1, left); + else + lefty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 1, left); + + /* coord of top face at integral y */ + + if (signdx > 0) { + ya = -ya; + xa = -xa; + } + + if (projectLeft) { + double xap = xa - projectXoff; + double yap = ya - projectYoff; + topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, -dy, dx, x1, y1, dx > 0, top); + } else + topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); + + /* coord of bottom face at integral y */ + + if (projectRight) { + double xap = xa + projectXoff; + double yap = ya + projectYoff; + bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, + -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya + projectYoff; + } else { + bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya; + } + + finaly = ICEIL (maxy) + y2; + + if (dx < 0) { + left->height = bottomy - lefty; + right->height = finaly - righty; + top->height = righty - topy; + } else { + right->height = bottomy - righty; + left->height = finaly - lefty; + top->height = lefty - topy; + } + bottom->height = finaly - bottomy; + miFillPolyHelper (pGC, foreground, spanData, topy, + bottom->height + bottomy - topy, lefts, rights, 2, 2); + } +} + +static SpanDataPtr +miSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt) +{ + if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop (pGC->alu)) + return (SpanDataPtr) NULL; + if (pGC->lineStyle == LineDoubleDash) + miInitSpanGroup (&spanData->bgGroup); + miInitSpanGroup (&spanData->fgGroup); + return spanData; +} + +static void +miCleanupSpanData (GCPtr pGC, SpanDataPtr spanData) +{ + if (pGC->lineStyle == LineDoubleDash) { + miFillUniqueSpanGroup (pGC, &spanData->bgGroup, FALSE); + miFreeSpanGroup (&spanData->bgGroup); + } + miFillUniqueSpanGroup (pGC, &spanData->fgGroup, TRUE); + miFreeSpanGroup (&spanData->fgGroup); +} + +void +miWideLine (GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + int x1, y1, x2, y2; + SpanDataRec spanDataRec; + SpanDataPtr spanData; + Boolean projectLeft, projectRight; + LineFaceRec leftFace, rightFace, prevRightFace; + LineFaceRec firstFace; + int first; + Boolean somethingDrawn = FALSE; + Boolean selfJoin; + + spanData = miSetupSpanData (pGC, &spanDataRec, npt); + x2 = pPts->x; + y2 = pPts->y; + first = TRUE; + selfJoin = FALSE; + if (npt > 1) { + if (mode == CoordModePrevious) { + int nptTmp; + DDXPointPtr pPtsTmp; + + x1 = x2; + y1 = y2; + nptTmp = npt; + pPtsTmp = pPts + 1; + while (--nptTmp) { + x1 += pPtsTmp->x; + y1 += pPtsTmp->y; + ++pPtsTmp; + } + if (x2 == x1 && y2 == y1) + selfJoin = TRUE; + } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) { + selfJoin = TRUE; + } + } + projectLeft = pGC->capStyle == CapProjecting && !selfJoin; + projectRight = FALSE; + while (--npt) { + x1 = x2; + y1 = y2; + ++pPts; + x2 = pPts->x; + y2 = pPts->y; + if (mode == CoordModePrevious) { + x2 += x1; + y2 += y1; + } + if (x1 != x2 || y1 != y2) { + somethingDrawn = TRUE; + if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) + projectRight = TRUE; + miWideSegment (pGC, TRUE, spanData, x1, y1, x2, y2, + projectLeft, projectRight, &leftFace, &rightFace); + if (first) { + if (selfJoin) + firstFace = leftFace; + else if (pGC->capStyle == CapRound) { + if (pGC->lineWidth == 1 && !spanData) + miLineOnePoint (pGC, TRUE, spanData, x1, y1); + else + miLineArc (pGC, TRUE, spanData, + &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); + } + } else { + miLineJoin (pGC, TRUE, spanData, &leftFace, &prevRightFace); + } + prevRightFace = rightFace; + first = FALSE; + projectLeft = FALSE; + } + if (npt == 1 && somethingDrawn) { + if (selfJoin) + miLineJoin (pGC, TRUE, spanData, &firstFace, &rightFace); + else if (pGC->capStyle == CapRound) { + if (pGC->lineWidth == 1 && !spanData) + miLineOnePoint (pGC, TRUE, spanData, x2, y2); + else + miLineArc (pGC, TRUE, spanData, + (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE); + } + } + } + /* handle crock where all points are coincedent */ + if (!somethingDrawn) { + projectLeft = pGC->capStyle == CapProjecting; + miWideSegment (pGC, TRUE, spanData, + x2, y2, x2, y2, projectLeft, projectLeft, &leftFace, &rightFace); + if (pGC->capStyle == CapRound) { + miLineArc (pGC, TRUE, spanData, + &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); + rightFace.dx = -1; /* sleezy hack to make it work */ + miLineArc (pGC, TRUE, spanData, + (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE); + } + } + if (spanData) + miCleanupSpanData (pGC, spanData); +} + +#define V_TOP 0 +#define V_RIGHT 1 +#define V_BOTTOM 2 +#define V_LEFT 3 + +static void +miWideDashSegment (GCPtr pGC, + SpanDataPtr spanData, + int *pDashOffset, + int *pDashIndex, + int x1, + int y1, + int x2, + int y2, + Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace) +{ + int dashIndex, dashRemain; + unsigned char *pDash; + double L, l; + double k; + PolyVertexRec vertices[4]; + PolyVertexRec saveRight = { 0, 0 }, saveBottom; + PolySlopeRec slopes[4]; + PolyEdgeRec left[4], right[4]; + LineFaceRec lcapFace, rcapFace; + int nleft, nright; + int h; + int y; + int dy, dx; + Boolean foreground; + double LRemain; + double r; + double rdx, rdy; + double dashDx, dashDy; + double saveK = 0.0; + Boolean first = TRUE; + double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; + + dx = x2 - x1; + dy = y2 - y1; + dashIndex = *pDashIndex; + pDash = pGC->dash; + dashRemain = pDash[dashIndex] - *pDashOffset; + + l = ((double) pGC->lineWidth) / 2.0; + if (dx == 0) { + L = dy; + rdx = 0; + rdy = l; + if (dy < 0) { + L = -dy; + rdy = -l; + } + } else if (dy == 0) { + L = dx; + rdx = l; + rdy = 0; + if (dx < 0) { + L = -dx; + rdx = -l; + } + } else { + L = hypot ((double) dx, (double) dy); + r = l / L; + + rdx = r * dx; + rdy = r * dy; + } + k = l * L; + LRemain = L; + /* All position comments are relative to a line with dx and dy > 0, + * but the code does not depend on this */ + /* top */ + slopes[V_TOP].dx = dx; + slopes[V_TOP].dy = dy; + slopes[V_TOP].k = k; + /* right */ + slopes[V_RIGHT].dx = -dy; + slopes[V_RIGHT].dy = dx; + slopes[V_RIGHT].k = 0; + /* bottom */ + slopes[V_BOTTOM].dx = -dx; + slopes[V_BOTTOM].dy = -dy; + slopes[V_BOTTOM].k = k; + /* left */ + slopes[V_LEFT].dx = dy; + slopes[V_LEFT].dy = -dx; + slopes[V_LEFT].k = 0; + + /* preload the start coordinates */ + vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; + vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; + + vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; + vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; + + if (projectLeft) { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + + slopes[V_LEFT].k = rdx * dx + rdy * dy; + } + + lcenterx = x1; + lcentery = y1; + + if (pGC->capStyle == CapRound) { + lcapFace.dx = dx; + lcapFace.dy = dy; + lcapFace.x = x1; + lcapFace.y = y1; + + rcapFace.dx = -dx; + rcapFace.dy = -dy; + rcapFace.x = x1; + rcapFace.y = y1; + } + while (LRemain > dashRemain) { + dashDx = (dashRemain * dx) / L; + dashDy = (dashRemain * dy) / L; + + rcenterx = lcenterx + dashDx; + rcentery = lcentery + dashDy; + + vertices[V_RIGHT].x += dashDx; + vertices[V_RIGHT].y += dashDy; + + vertices[V_BOTTOM].x += dashDx; + vertices[V_BOTTOM].y += dashDy; + + slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; + + if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) { + if (pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) { + saveRight = vertices[V_RIGHT]; + saveBottom = vertices[V_BOTTOM]; + saveK = slopes[V_RIGHT].k; + + if (!first) { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + + slopes[V_LEFT].k = vertices[V_LEFT].x * + slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx; + } + + vertices[V_RIGHT].x += rdx; + vertices[V_RIGHT].y += rdy; + + vertices[V_BOTTOM].x += rdx; + vertices[V_BOTTOM].y += rdy; + + slopes[V_RIGHT].k = vertices[V_RIGHT].x * + slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx; + } + y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, left, right, &nleft, &nright, &h); + foreground = (dashIndex & 1) == 0; + miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright); + + if (pGC->lineStyle == LineOnOffDash) { + switch (pGC->capStyle) { + case CapProjecting: + vertices[V_BOTTOM] = saveBottom; + vertices[V_RIGHT] = saveRight; + slopes[V_RIGHT].k = saveK; + break; + case CapRound: + if (!first) { + if (dx < 0) { + lcapFace.xa = -vertices[V_LEFT].x; + lcapFace.ya = -vertices[V_LEFT].y; + lcapFace.k = slopes[V_LEFT].k; + } else { + lcapFace.xa = vertices[V_TOP].x; + lcapFace.ya = vertices[V_TOP].y; + lcapFace.k = -slopes[V_LEFT].k; + } + miLineArc (pGC, foreground, spanData, + &lcapFace, (LineFacePtr) NULL, lcenterx, lcentery, FALSE); + } + if (dx < 0) { + rcapFace.xa = vertices[V_BOTTOM].x; + rcapFace.ya = vertices[V_BOTTOM].y; + rcapFace.k = slopes[V_RIGHT].k; + } else { + rcapFace.xa = -vertices[V_RIGHT].x; + rcapFace.ya = -vertices[V_RIGHT].y; + rcapFace.k = -slopes[V_RIGHT].k; + } + miLineArc (pGC, foreground, spanData, + (LineFacePtr) NULL, &rcapFace, rcenterx, rcentery, FALSE); + break; + } + } + } + LRemain -= dashRemain; + ++dashIndex; + if (dashIndex == pGC->numInDashList) + dashIndex = 0; + dashRemain = pDash[dashIndex]; + + lcenterx = rcenterx; + lcentery = rcentery; + + vertices[V_TOP] = vertices[V_RIGHT]; + vertices[V_LEFT] = vertices[V_BOTTOM]; + slopes[V_LEFT].k = -slopes[V_RIGHT].k; + first = FALSE; + } + + if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) { + vertices[V_TOP].x -= dx; + vertices[V_TOP].y -= dy; + + vertices[V_LEFT].x -= dx; + vertices[V_LEFT].y -= dy; + + vertices[V_RIGHT].x = rdy; + vertices[V_RIGHT].y = -rdx; + + vertices[V_BOTTOM].x = -rdy; + vertices[V_BOTTOM].y = rdx; + + + if (projectRight) { + vertices[V_RIGHT].x += rdx; + vertices[V_RIGHT].y += rdy; + + vertices[V_BOTTOM].x += rdx; + vertices[V_BOTTOM].y += rdy; + slopes[V_RIGHT].k = vertices[V_RIGHT].x * + slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx; + } else + slopes[V_RIGHT].k = 0; + + if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) { + vertices[V_TOP].x -= rdx; + vertices[V_TOP].y -= rdy; + + vertices[V_LEFT].x -= rdx; + vertices[V_LEFT].y -= rdy; + slopes[V_LEFT].k = vertices[V_LEFT].x * + slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx; + } else + slopes[V_LEFT].k += dx * dx + dy * dy; + + + y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, left, right, &nleft, &nright, &h); + + foreground = (dashIndex & 1) == 0; + miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright); + if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapRound) { + lcapFace.x = x2; + lcapFace.y = y2; + if (dx < 0) { + lcapFace.xa = -vertices[V_LEFT].x; + lcapFace.ya = -vertices[V_LEFT].y; + lcapFace.k = slopes[V_LEFT].k; + } else { + lcapFace.xa = vertices[V_TOP].x; + lcapFace.ya = vertices[V_TOP].y; + lcapFace.k = -slopes[V_LEFT].k; + } + miLineArc (pGC, foreground, spanData, + &lcapFace, (LineFacePtr) NULL, rcenterx, rcentery, FALSE); + } + } + dashRemain = (int)(((double) dashRemain) - LRemain); + if (dashRemain == 0) { + dashIndex++; + if (dashIndex == pGC->numInDashList) + dashIndex = 0; + dashRemain = pDash[dashIndex]; + } + + leftFace->x = x1; + leftFace->y = y1; + leftFace->dx = dx; + leftFace->dy = dy; + leftFace->xa = rdy; + leftFace->ya = -rdx; + leftFace->k = k; + + rightFace->x = x2; + rightFace->y = y2; + rightFace->dx = -dx; + rightFace->dy = -dy; + rightFace->xa = -rdy; + rightFace->ya = rdx; + rightFace->k = k; + + *pDashIndex = dashIndex; + *pDashOffset = pDash[dashIndex] - dashRemain; +} + +void +miWideDash (GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + int x1, y1, x2, y2; + Boolean foreground; + Boolean projectLeft, projectRight; + LineFaceRec leftFace, rightFace, prevRightFace; + LineFaceRec firstFace; + int first; + int dashIndex, dashOffset; + int prevDashIndex; + SpanDataRec spanDataRec; + SpanDataPtr spanData; + Boolean somethingDrawn = FALSE; + Boolean selfJoin; + Boolean endIsFg = FALSE, startIsFg = FALSE; + Boolean firstIsFg = FALSE, prevIsFg = FALSE; + + if (npt == 0) + return; + spanData = miSetupSpanData (pGC, &spanDataRec, npt); + x2 = pPts->x; + y2 = pPts->y; + first = TRUE; + selfJoin = FALSE; + if (mode == CoordModePrevious) { + int nptTmp; + DDXPointPtr pPtsTmp; + + x1 = x2; + y1 = y2; + nptTmp = npt; + pPtsTmp = pPts + 1; + while (--nptTmp) { + x1 += pPtsTmp->x; + y1 += pPtsTmp->y; + ++pPtsTmp; + } + if (x2 == x1 && y2 == y1) + selfJoin = TRUE; + } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) { + selfJoin = TRUE; + } + projectLeft = pGC->capStyle == CapProjecting && !selfJoin; + projectRight = FALSE; + dashIndex = 0; + dashOffset = 0; + miStepDash ((int) pGC->dashOffset, &dashIndex, + pGC->dash, (int) pGC->numInDashList, &dashOffset); + while (--npt) { + x1 = x2; + y1 = y2; + ++pPts; + x2 = pPts->x; + y2 = pPts->y; + if (mode == CoordModePrevious) { + x2 += x1; + y2 += y1; + } + if (x1 != x2 || y1 != y2) { + somethingDrawn = TRUE; + if (npt == 1 && pGC->capStyle == CapProjecting && (!selfJoin || !firstIsFg)) + projectRight = TRUE; + prevDashIndex = dashIndex; + miWideDashSegment (pGC, spanData, &dashOffset, &dashIndex, + x1, y1, x2, y2, projectLeft, projectRight, &leftFace, &rightFace); + startIsFg = !(prevDashIndex & 1); + endIsFg = (dashIndex & 1) ^ (dashOffset != 0); + if (pGC->lineStyle == LineDoubleDash || startIsFg) { + foreground = startIsFg; + if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) { + if (first && selfJoin) { + firstFace = leftFace; + firstIsFg = startIsFg; + } else if (pGC->capStyle == CapRound) + miLineArc (pGC, foreground, spanData, + &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); + } else { + miLineJoin (pGC, foreground, spanData, &leftFace, &prevRightFace); + } + } + prevRightFace = rightFace; + prevIsFg = endIsFg; + first = FALSE; + projectLeft = FALSE; + } + if (npt == 1 && somethingDrawn) { + if (pGC->lineStyle == LineDoubleDash || endIsFg) { + foreground = endIsFg; + if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) { + miLineJoin (pGC, foreground, spanData, &firstFace, &rightFace); + } else { + if (pGC->capStyle == CapRound) + miLineArc (pGC, foreground, spanData, + (LineFacePtr) NULL, &rightFace, + (double) 0.0, (double) 0.0, TRUE); + } + } else { + /* glue a cap to the start of the line if + * we're OnOffDash and ended on odd dash + */ + if (selfJoin && firstIsFg) { + foreground = TRUE; + if (pGC->capStyle == CapProjecting) + miLineProjectingCap (pGC, foreground, spanData, + &firstFace, TRUE, (double) 0.0, (double) 0.0, TRUE); + else if (pGC->capStyle == CapRound) + miLineArc (pGC, foreground, spanData, + &firstFace, (LineFacePtr) NULL, + (double) 0.0, (double) 0.0, TRUE); + } + } + } + } + /* handle crock where all points are coincident */ + if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) { + /* not the same as endIsFg computation above */ + foreground = (dashIndex & 1) == 0; + switch (pGC->capStyle) { + case CapRound: + miLineArc (pGC, foreground, spanData, + (LineFacePtr) NULL, (LineFacePtr) NULL, (double) x2, (double) y2, FALSE); + break; + case CapProjecting: + x1 = pGC->lineWidth; + miFillRectPolyHelper (pGC, foreground, spanData, + x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); + break; + } + } + if (spanData) + miCleanupSpanData (pGC, spanData); +} + +#undef ExchangeSpans +#define ExchangeSpans(a, b) \ +{ \ + DDXPointRec tpt; \ + int tw; \ + \ + tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + +static void QuickSortSpans( + DDXPointRec spans[], + int widths[], + int numSpans) +{ + int y; + int i, j, m; + DDXPointPtr r; + + /* Always called with numSpans > 1 */ + /* Sorts only by y, doesn't bother to sort by x */ + + do + { + if (numSpans < 9) + { + /* Do insertion sort */ + int yprev; + + yprev = spans[0].y; + i = 1; + do + { /* while i != numSpans */ + y = spans[i].y; + if (yprev > y) + { + /* spans[i] is out of order. Move into proper location. */ + DDXPointRec tpt; + int tw, k; + + for (j = 0; y >= spans[j].y; j++) {} + tpt = spans[i]; + tw = widths[i]; + for (k = i; k != j; k--) + { + spans[k] = spans[k-1]; + widths[k] = widths[k-1]; + } + spans[j] = tpt; + widths[j] = tw; + y = spans[i].y; + } /* if out of order */ + yprev = y; + i++; + } while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + y = spans[0].y; + + /* Partition array */ + i = 0; + j = numSpans; + do + { + r = &(spans[i]); + do + { + r++; + i++; + } while (i != numSpans && r->y < y); + r = &(spans[j]); + do + { + r--; + j--; + } while (y < r->y); + if (i < j) + ExchangeSpans(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans(0, j); + + /* Recurse */ + if (numSpans-j-1 > 1) + QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); + numSpans = j; + } while (numSpans > 1); +} + +#define NextBand() \ +{ \ + clipy1 = pboxBandStart->y1; \ + clipy2 = pboxBandStart->y2; \ + pboxBandEnd = pboxBandStart + 1; \ + while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ + pboxBandEnd++; \ + } \ + for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ +} + +/* + Clip a list of scanlines to a region. The caller has allocated the + space. FSorted is non-zero if the scanline origins are in ascending + order. + returns the number of new, clipped scanlines. +*/ + +int spice_canvas_clip_spans(pixman_region32_t *prgnDst, + DDXPointPtr ppt, + int *pwidth, + int nspans, + DDXPointPtr pptNew, + int *pwidthNew, + int fSorted) +{ + DDXPointPtr pptLast; + int *pwidthNewStart; /* the vengeance of Xerox! */ + int y, x1, x2; + int numRects; + pixman_box32_t *pboxBandStart; + + pptLast = ppt + nspans; + pwidthNewStart = pwidthNew; + + pboxBandStart = pixman_region32_rectangles (prgnDst, &numRects); + + if (numRects == 1) { + /* Do special fast code with clip boundaries in registers(?) */ + /* It doesn't pay much to make use of fSorted in this case, + so we lump everything together. */ + + int clipx1, clipx2, clipy1, clipy2; + + clipx1 = pboxBandStart->x1; + clipy1 = pboxBandStart->y1; + clipx2 = pboxBandStart->x2; + clipy2 = pboxBandStart->y2; + + for (; ppt != pptLast; ppt++, pwidth++) { + y = ppt->y; + x1 = ppt->x; + if (clipy1 <= y && y < clipy2) { + x2 = x1 + *pwidth; + if (x1 < clipx1) + x1 = clipx1; + if (x2 > clipx2) + x2 = clipx2; + if (x1 < x2) { + /* part of span in clip rectangle */ + pptNew->x = x1; + pptNew->y = y; + *pwidthNew = x2 - x1; + pptNew++; + pwidthNew++; + } + } + } /* end for */ + } else if (numRects != 0) { + /* Have to clip against many boxes */ + pixman_box32_t *pboxBandEnd, *pbox, *pboxLast; + int clipy1, clipy2; + + /* In this case, taking advantage of sorted spans gains more than + the sorting costs. */ + if ((! fSorted) && (nspans > 1)) + QuickSortSpans(ppt, pwidth, nspans); + + pboxLast = pboxBandStart + numRects; + + NextBand(); + + for (; ppt != pptLast; ) { + y = ppt->y; + if (y < clipy2) { + /* span is in the current band */ + pbox = pboxBandStart; + x1 = ppt->x; + x2 = x1 + *pwidth; + do { /* For each box in band */ + int newx1, newx2; + + newx1 = x1; + newx2 = x2; + if (newx1 < pbox->x1) + newx1 = pbox->x1; + if (newx2 > pbox->x2) + newx2 = pbox->x2; + if (newx1 < newx2) { + /* Part of span in clip rectangle */ + pptNew->x = newx1; + pptNew->y = y; + *pwidthNew = newx2 - newx1; + pptNew++; + pwidthNew++; + } + pbox++; + } while (pbox != pboxBandEnd); + ppt++; + pwidth++; + } else { + /* Move to next band, adjust ppt as needed */ + pboxBandStart = pboxBandEnd; + if (pboxBandStart == pboxLast) + break; /* We're completely done */ + NextBand(); + } + } + } + return (pwidthNew - pwidthNewStart); +} diff --git a/spice-common/common/lines.h b/spice-common/common/lines.h new file mode 100644 index 0000000..d98686f --- /dev/null +++ b/spice-common/common/lines.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +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 +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef LINES_H +#define LINES_H + +#include +#include +#include + +#include "pixman_utils.h" +#include "draw.h" + +SPICE_BEGIN_DECLS + +typedef struct lineGC lineGC; + +typedef struct { + void (*FillSpans)(lineGC * pGC, + int num_spans, SpicePoint * points, int *widths, + int sorted, int foreground); + void (*FillRects)(lineGC * pGC, + int nun_rects, pixman_rectangle32_t * rects, + int foreground); +} lineGCOps; + +struct lineGC { + int width; + int height; + unsigned char alu; + unsigned short lineWidth; + unsigned short dashOffset; + unsigned short numInDashList; + unsigned char *dash; + unsigned int lineStyle:2; + unsigned int capStyle:2; + unsigned int joinStyle:2; + lineGCOps *ops; +}; + +/* CoordinateMode for drawing routines */ + +#define CoordModeOrigin 0 /* relative to the origin */ +#define CoordModePrevious 1 /* relative to previous point */ + +/* LineStyle */ + +#define LineSolid 0 +#define LineOnOffDash 1 +#define LineDoubleDash 2 + +/* capStyle */ + +#define CapNotLast 0 +#define CapButt 1 +#define CapRound 2 +#define CapProjecting 3 + +/* joinStyle */ + +#define JoinMiter 0 +#define JoinRound 1 +#define JoinBevel 2 + +extern void spice_canvas_zero_line(lineGC *pgc, + int mode, + int num_points, + SpicePoint * points); +extern void spice_canvas_zero_dash_line(lineGC * pgc, + int mode, + int n_points, + SpicePoint * points); +extern void spice_canvas_wide_dash_line(lineGC * pGC, + int mode, + int num_points, + SpicePoint * points); +extern void spice_canvas_wide_line(lineGC *pGC, + int mode, + int num_points, + SpicePoint * points); +extern int spice_canvas_clip_spans(pixman_region32_t *clip_region, + SpicePoint *points, + int *widths, + int num_spans, + SpicePoint *new_points, + int *new_widths, + int sorted); + +SPICE_END_DECLS + +#endif /* LINES_H */ diff --git a/spice-common/common/log.c b/spice-common/common/log.c new file mode 100644 index 0000000..20d4597 --- /dev/null +++ b/spice-common/common/log.c @@ -0,0 +1,190 @@ +/* + Copyright (C) 2012-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif + +#include "log.h" +#include "backtrace.h" + +static int glib_debug_level = 0; +static int abort_level = -1; + +#ifndef SPICE_ABORT_LEVEL_DEFAULT +#ifdef SPICE_DISABLE_ABORT +#define SPICE_ABORT_LEVEL_DEFAULT -1 +#else +#define SPICE_ABORT_LEVEL_DEFAULT SPICE_LOG_LEVEL_CRITICAL +#endif +#endif + +static GLogLevelFlags spice_log_level_to_glib(SpiceLogLevel level) +{ + static const GLogLevelFlags glib_levels[] = { + [ SPICE_LOG_LEVEL_ERROR ] = G_LOG_LEVEL_ERROR, + [ SPICE_LOG_LEVEL_CRITICAL ] = G_LOG_LEVEL_CRITICAL, + [ SPICE_LOG_LEVEL_WARNING ] = G_LOG_LEVEL_WARNING, + [ SPICE_LOG_LEVEL_INFO ] = G_LOG_LEVEL_INFO, + [ SPICE_LOG_LEVEL_DEBUG ] = G_LOG_LEVEL_DEBUG, + }; + g_return_val_if_fail (level >= 0, G_LOG_LEVEL_ERROR); + g_return_val_if_fail (level < G_N_ELEMENTS(glib_levels), G_LOG_LEVEL_DEBUG); + + return glib_levels[level]; +} + +static void spice_log_set_debug_level(void) +{ + if (glib_debug_level == 0) { + const char *debug_str = g_getenv("SPICE_DEBUG_LEVEL"); + if (debug_str != NULL) { + int debug_level; + char *debug_env; + + /* FIXME: To be removed after enough deprecation time */ + g_warning("Setting SPICE_DEBUG_LEVEL is deprecated, use G_MESSAGES_DEBUG instead"); + debug_level = atoi(debug_str); + if (debug_level > SPICE_LOG_LEVEL_DEBUG) { + debug_level = SPICE_LOG_LEVEL_DEBUG; + } + glib_debug_level = spice_log_level_to_glib(debug_level); + + /* If the debug level is too high, make sure we don't try to enable + * display of glib debug logs */ + if (debug_level < SPICE_LOG_LEVEL_INFO) + return; + + /* Make sure GLib default log handler will show the debug messages. Messing with + * environment variables like this is ugly, but this only happens when the legacy + * SPICE_DEBUG_LEVEL is used + */ + debug_env = (char *)g_getenv("G_MESSAGES_DEBUG"); + if (debug_env == NULL) { + g_setenv("G_MESSAGES_DEBUG", SPICE_LOG_DOMAIN, FALSE); + } else { + debug_env = g_strconcat(debug_env, ":", SPICE_LOG_DOMAIN, NULL); + g_setenv("G_MESSAGES_DEBUG", SPICE_LOG_DOMAIN, FALSE); + g_free(debug_env); + } + } + } +} + +static void spice_log_set_abort_level(void) +{ + if (abort_level == -1) { + const char *abort_str = g_getenv("SPICE_ABORT_LEVEL"); + if (abort_str != NULL) { + GLogLevelFlags glib_abort_level; + + /* FIXME: To be removed after enough deprecation time */ + g_warning("Setting SPICE_ABORT_LEVEL is deprecated, use G_DEBUG instead"); + abort_level = atoi(abort_str); + glib_abort_level = spice_log_level_to_glib(abort_level); + if (glib_abort_level != 0) { + unsigned int fatal_mask = G_LOG_FATAL_MASK; + while (glib_abort_level >= G_LOG_LEVEL_ERROR) { + fatal_mask |= glib_abort_level; + glib_abort_level >>= 1; + } + g_log_set_fatal_mask(SPICE_LOG_DOMAIN, fatal_mask); + } + } else { + abort_level = SPICE_ABORT_LEVEL_DEFAULT; + } + } +} + +static void spice_logger(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + if (glib_debug_level != 0) { + if ((log_level & G_LOG_LEVEL_MASK) > glib_debug_level) + return; // do not print anything + } + g_log_default_handler(log_domain, log_level, message, NULL); +} + +SPICE_CONSTRUCTOR_FUNC(spice_log_init) +{ + + spice_log_set_debug_level(); + spice_log_set_abort_level(); + g_log_set_handler(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + spice_logger, NULL); + /* Threading is always enabled from 2.31.0 onwards */ + /* Our logging is potentially used from different threads. + * Older glibs require that g_thread_init() is called when + * doing that. */ +#if !GLIB_CHECK_VERSION(2, 31, 0) + if (!g_thread_supported()) + g_thread_init(NULL); +#endif +} + +static void spice_logv(const char *log_domain, + SpiceLogLevel log_level, + const char *strloc, + const char *function, + const char *format, + va_list args) +{ + GString *log_msg; + + g_return_if_fail(spice_log_level_to_glib(log_level) != 0); + + log_msg = g_string_new(NULL); + if (strloc && function) { + g_string_append_printf(log_msg, "%s:%s: ", strloc, function); + } + if (format) { + g_string_append_vprintf(log_msg, format, args); + } + g_log(log_domain, spice_log_level_to_glib(log_level), "%s", log_msg->str); + g_string_free(log_msg, TRUE); + + if (abort_level != -1 && abort_level >= (int) log_level) { + spice_backtrace(); + abort(); + } +} + +void spice_log(const char *log_domain, + SpiceLogLevel log_level, + const char *strloc, + const char *function, + const char *format, + ...) +{ + va_list args; + + va_start (args, format); + spice_logv (log_domain, log_level, strloc, function, format, args); + va_end (args); +} diff --git a/spice-common/common/log.h b/spice-common/common/log.h new file mode 100644 index 0000000..0e03f59 --- /dev/null +++ b/spice-common/common/log.h @@ -0,0 +1,111 @@ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef H_SPICE_LOG +#define H_SPICE_LOG + +#include + +#include +#include +#include "macros.h" + +SPICE_BEGIN_DECLS + +#ifndef SPICE_LOG_DOMAIN +#define SPICE_LOG_DOMAIN "Spice" +#endif + +#define SPICE_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) + +typedef enum { + SPICE_LOG_LEVEL_ERROR, + SPICE_LOG_LEVEL_CRITICAL, + SPICE_LOG_LEVEL_WARNING, + SPICE_LOG_LEVEL_INFO, + SPICE_LOG_LEVEL_DEBUG, +} SpiceLogLevel; + +void spice_log(const char *log_domain, + SpiceLogLevel log_level, + const char *strloc, + const char *function, + const char *format, + ...) SPICE_ATTR_PRINTF(5, 6); + +#define spice_return_if_fail(x) G_STMT_START { \ + if G_LIKELY(x) { } else { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_CRITICAL, SPICE_STRLOC, G_STRFUNC, "condition `%s' failed", #x); \ + return; \ + } \ +} G_STMT_END + +#define spice_return_val_if_fail(x, val) G_STMT_START { \ + if G_LIKELY(x) { } else { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_CRITICAL, SPICE_STRLOC, __FUNCTION__, "condition `%s' failed", #x); \ + return (val); \ + } \ +} G_STMT_END + +#define spice_warn_if_reached() G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_WARNING, SPICE_STRLOC, __FUNCTION__, "should not be reached"); \ +} G_STMT_END + +#define spice_printerr(format, ...) G_STMT_START { \ + fprintf(stderr, "%s: " format "\n", __FUNCTION__, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_info(format, ...) G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_INFO, SPICE_STRLOC, __FUNCTION__, format, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_debug(format, ...) G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_DEBUG, SPICE_STRLOC, __FUNCTION__, format, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_warning(format, ...) G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_WARNING, SPICE_STRLOC, __FUNCTION__, format, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_critical(format, ...) G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_CRITICAL, SPICE_STRLOC, __FUNCTION__, format, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_error(format, ...) G_STMT_START { \ + spice_log(SPICE_LOG_DOMAIN, SPICE_LOG_LEVEL_ERROR, SPICE_STRLOC, __FUNCTION__, format, ## __VA_ARGS__); \ +} G_STMT_END + +#define spice_warn_if_fail(x) G_STMT_START { \ + if G_LIKELY(x) { } else { \ + spice_warning("condition `%s' failed", #x); \ + } \ +} G_STMT_END + +#define spice_assert(x) G_STMT_START { \ + if G_LIKELY(x) { } else { \ + spice_error("assertion `%s' failed", #x); \ + } \ +} G_STMT_END + +/* FIXME: improve that some day.. */ +#define spice_static_assert(x) SPICE_STMT_START { \ + spice_assert(x); \ +} SPICE_STMT_END + +SPICE_END_DECLS + +#endif /* H_SPICE_LOG */ diff --git a/spice-common/common/lz.c b/spice-common/common/lz.c new file mode 100644 index 0000000..2589223 --- /dev/null +++ b/spice-common/common/lz.c @@ -0,0 +1,753 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + + Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . + + This file incorporates work covered by the following copyright and + permission notice: + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + 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. + +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "spice_common.h" +#include "lz.h" + +#define HASH_LOG 13 +#define HASH_SIZE (1 << HASH_LOG) +#define HASH_MASK (HASH_SIZE - 1) + + +typedef struct LzImageSegment LzImageSegment; +struct LzImageSegment { + uint8_t *lines; + uint8_t *lines_end; + unsigned int size_delta; // total size of the previous segments in units of + // pixels for rgb and bytes for plt. + LzImageSegment *next; +}; + +// TODO: pack? +typedef struct HashEntry { + LzImageSegment *image_seg; + uint8_t *ref; +} HashEntry; + +typedef struct Encoder { + LzUsrContext *usr; + + LzImageType type; + const SpicePalette *palette; // for decoding images with palettes to rgb + int stride; // stride is in bytes. For rgb must be equal to + // width*bytes_per_pix. + // For palettes stride can be bigger than width/pixels_per_byte by 1 only if + // width%pixels_per_byte != 0. + int height; + int width; // the original width (in pixels) + + LzImageSegment *head_image_segs; + LzImageSegment *tail_image_segs; + LzImageSegment *free_image_segs; + + // the dictionary hash table is composed (1) a pointer to the segment the word was found in + // (2) a pointer to the first byte in the segment that matches the word + HashEntry htab[HASH_SIZE]; + + uint8_t *io_start; + uint8_t *io_now; + uint8_t *io_end; + size_t io_bytes_count; + + uint8_t *io_last_copy; // pointer to the last byte in which copy count was written +} Encoder; + +/****************************************************/ +/* functions for managing the pool of image segments*/ +/****************************************************/ +static inline LzImageSegment *lz_alloc_image_seg(Encoder *encoder); +static void lz_reset_image_seg(Encoder *encoder); +static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines, + unsigned int num_first_lines); + + +// return a free image segment if one exists. Make allocation if needed. adds it to the +// tail of the image segments lists +static inline LzImageSegment *lz_alloc_image_seg(Encoder *encoder) +{ + LzImageSegment *ret; + + if (encoder->free_image_segs) { + ret = encoder->free_image_segs; + encoder->free_image_segs = ret->next; + } else { + if (!(ret = (LzImageSegment *)encoder->usr->malloc(encoder->usr, sizeof(*ret)))) { + return NULL; + } + } + + ret->next = NULL; + if (encoder->tail_image_segs) { + encoder->tail_image_segs->next = ret; + } + encoder->tail_image_segs = ret; + + if (!encoder->head_image_segs) { + encoder->head_image_segs = ret; + } + + return ret; +} + +// adding seg to the head of free segments (lz_reset_image_seg removes it from used ones) +static inline void __lz_free_image_seg(Encoder *encoder, LzImageSegment *seg) +{ + seg->next = encoder->free_image_segs; + encoder->free_image_segs = seg; +} + +// moves all the used image segments to the free pool +static void lz_reset_image_seg(Encoder *encoder) +{ + while (encoder->head_image_segs) { + LzImageSegment *seg = encoder->head_image_segs; + encoder->head_image_segs = seg->next; + __lz_free_image_seg(encoder, seg); + } + encoder->tail_image_segs = NULL; +} + +static void lz_dealloc_free_segments(Encoder *encoder) +{ + while (encoder->free_image_segs) { + LzImageSegment *seg = encoder->free_image_segs; + encoder->free_image_segs = seg->next; + encoder->usr->free(encoder->usr, seg); + } +} + +// return FALSE when operation fails (due to failure in allocation) +static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines, + unsigned int num_first_lines) +{ + LzImageSegment *image_seg; + uint32_t size_delta = 0; + unsigned int num_lines = num_first_lines; + uint8_t* lines = first_lines; + int row; + + spice_return_val_if_fail(!encoder->head_image_segs, FALSE); + + image_seg = lz_alloc_image_seg(encoder); + if (!image_seg) { + goto error_1; + } + + image_seg->lines = lines; + image_seg->lines_end = lines + num_lines * encoder->stride; + image_seg->size_delta = size_delta; + + size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type]; + + for (row = num_first_lines; row < encoder->height; row += num_lines) { + num_lines = encoder->usr->more_lines(encoder->usr, &lines); + if (num_lines <= 0) { + encoder->usr->error(encoder->usr, "more lines failed\n"); + } + image_seg = lz_alloc_image_seg(encoder); + + if (!image_seg) { + goto error_1; + } + + image_seg->lines = lines; + image_seg->lines_end = lines + num_lines * encoder->stride; + image_seg->size_delta = size_delta; + + size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type]; + } + + return TRUE; +error_1: + lz_reset_image_seg(encoder); + return FALSE; +} + +/************************************************************************** +* Handling encoding and decoding of a byte +***************************************************************************/ +static inline int more_io_bytes(Encoder *encoder) +{ + uint8_t *io_ptr; + int num_io_bytes = encoder->usr->more_space(encoder->usr, &io_ptr); + encoder->io_bytes_count += num_io_bytes; + encoder->io_now = io_ptr; + encoder->io_end = encoder->io_now + num_io_bytes; + return num_io_bytes; +} + +static inline void encode(Encoder *encoder, uint8_t byte) +{ + if (encoder->io_now == encoder->io_end) { + if (more_io_bytes(encoder) <= 0) { + encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); + } + spice_return_if_fail(encoder->io_now); + } + + spice_return_if_fail(encoder->io_now < encoder->io_end); + *(encoder->io_now++) = byte; +} + +static inline void encode_32(Encoder *encoder, unsigned int word) +{ + encode(encoder, (uint8_t)(word >> 24)); + encode(encoder, (uint8_t)(word >> 16) & 0x0000ff); + encode(encoder, (uint8_t)(word >> 8) & 0x0000ff); + encode(encoder, (uint8_t)(word & 0x0000ff)); +} + +static inline void encode_copy_count(Encoder *encoder, uint8_t copy_count) +{ + encode(encoder, copy_count); + encoder->io_last_copy = encoder->io_now - 1; // io_now cannot be the first byte of the buffer +} + +static inline void update_copy_count(Encoder *encoder, uint8_t copy_count) +{ + spice_return_if_fail(encoder->io_last_copy); + *(encoder->io_last_copy) = copy_count; +} + +static inline void encode_level(Encoder *encoder, uint8_t level_code) +{ + *(encoder->io_start) |= level_code; +} + +// decrease the io ptr by 1 +static inline void compress_output_prev(Encoder *encoder) +{ + // io_now cannot be the first byte of the buffer + encoder->io_now--; + // the function should be called only when copy count is written unnecessarily by lz_compress + spice_return_if_fail(encoder->io_now == encoder->io_last_copy); +} + +static int encoder_reset(Encoder *encoder, uint8_t *io_ptr, uint8_t *io_ptr_end) +{ + spice_return_val_if_fail(io_ptr <= io_ptr_end, FALSE); + + encoder->io_bytes_count = io_ptr_end - io_ptr; + encoder->io_start = io_ptr; + encoder->io_now = io_ptr; + encoder->io_end = io_ptr_end; + encoder->io_last_copy = NULL; + + return TRUE; +} + +static inline uint8_t decode(Encoder *encoder) +{ + if (encoder->io_now == encoder->io_end) { + int num_io_bytes = more_io_bytes(encoder); + if (num_io_bytes <= 0) { + encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); + } + spice_assert(encoder->io_now); + } + spice_assert(encoder->io_now < encoder->io_end); + return *(encoder->io_now++); +} + +static inline uint32_t decode_32(Encoder *encoder) +{ + uint32_t word = 0; + word |= decode(encoder); + word <<= 8; + word |= decode(encoder); + word <<= 8; + word |= decode(encoder); + word <<= 8; + word |= decode(encoder); + return word; +} + +static inline int is_io_to_decode_end(Encoder *encoder) +{ + if (encoder->io_now != encoder->io_end) { + return FALSE; + } else { + int num_io_bytes = more_io_bytes(encoder); //disable inline optimizations + return (num_io_bytes <= 0); + } +} + +/******************************************************************* +* intialization and finalization of lz +********************************************************************/ +static int init_encoder(Encoder *encoder, LzUsrContext *usr) +{ + encoder->usr = usr; + encoder->free_image_segs = NULL; + encoder->head_image_segs = NULL; + encoder->tail_image_segs = NULL; + return TRUE; +} + +LzContext *lz_create(LzUsrContext *usr) +{ + Encoder *encoder; + + if (!usr || !usr->error || !usr->warn || !usr->info || !usr->malloc || + !usr->free || !usr->more_space || !usr->more_lines) { + return NULL; + } + + if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) { + return NULL; + } + + if (!init_encoder(encoder, usr)) { + usr->free(usr, encoder); + return NULL; + } + return (LzContext *)encoder; +} + +void lz_destroy(LzContext *lz) +{ + Encoder *encoder = (Encoder *)lz; + + if (!lz) { + return; + } + + if (encoder->head_image_segs) { + encoder->usr->error(encoder->usr, "%s: used_image_segments not empty\n", __FUNCTION__); + lz_reset_image_seg(encoder); + } + lz_dealloc_free_segments(encoder); + + encoder->usr->free(encoder->usr, encoder); +} + +/******************************************************************* +* encoding and decoding the image +********************************************************************/ +/* + * Give hints to the compiler for branch prediction optimization. + */ +#if defined(__GNUC__) && (__GNUC__ > 2) +#define LZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) +#define LZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) +#else +#define LZ_EXPECT_CONDITIONAL(c) (c) +#define LZ_UNEXPECT_CONDITIONAL(c) (c) +#endif + + +#ifdef __GNUC__ +#define ATTR_PACKED __attribute__ ((__packed__)) +#else +#define ATTR_PACKED +#pragma pack(push) +#pragma pack(1) +#endif + + +/* the palette images will be treated as one byte pixels. Their width should be transformed + accordingly. +*/ +typedef struct ATTR_PACKED one_byte_pixel_t { + uint8_t a; +} one_byte_pixel_t; + +typedef struct ATTR_PACKED rgb32_pixel_t { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t pad; +} rgb32_pixel_t; + +typedef struct ATTR_PACKED rgb24_pixel_t { + uint8_t b; + uint8_t g; + uint8_t r; +} rgb24_pixel_t; + +typedef uint16_t rgb16_pixel_t; + +#ifndef __GNUC__ +#pragma pack(pop) +#endif + +#undef ATTR_PACKED + + +#define MAX_COPY 32 +#define MAX_LEN 264 /* 256 + 8 */ +#define BOUND_OFFSET 2 +#define LIMIT_OFFSET 6 +#define MIN_FILE_SIZE 4 +#define COMP_LEVEL_SIZE_LIMIT 65536 + +// TODO: implemented lz2. should lz1 be an option (no RLE + distance limitation of MAX_DISTANCE) +// TODO: I think MAX_FARDISTANCE can be changed easily to 2^29 +// (and maybe even more when pixel > byte). +// i.e. we can support 512M Bytes/Pixels distance instead of only ~68K. +#define MAX_DISTANCE 8191 // 2^13 +#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1) // ~2^16+2^13 + + +#define LZ_PLT +#include "lz_compress_tmpl.c" +#define LZ_PLT +#include "lz_decompress_tmpl.c" + +#define LZ_PLT +#define PLT8 +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_PLT +#define PLT4_BE +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_PLT +#define PLT4_LE +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_PLT +#define PLT1_BE +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_PLT +#define PLT1_LE +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_A8 +#include "lz_compress_tmpl.c" +#define LZ_A8 +#include "lz_decompress_tmpl.c" +#define LZ_A8 +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_RGB16 +#include "lz_compress_tmpl.c" +#define LZ_RGB16 +#include "lz_decompress_tmpl.c" +#define LZ_RGB16 +#define TO_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_RGB24 +#include "lz_compress_tmpl.c" +#define LZ_RGB24 +#include "lz_decompress_tmpl.c" + + +#define LZ_RGB32 +#include "lz_compress_tmpl.c" +#define LZ_RGB32 +#include "lz_decompress_tmpl.c" + +#define LZ_RGB_ALPHA +#include "lz_compress_tmpl.c" +#define LZ_RGB_ALPHA +#include "lz_decompress_tmpl.c" + +#undef LZ_UNEXPECT_CONDITIONAL +#undef LZ_EXPECT_CONDITIONAL + +int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down, + uint8_t *lines, unsigned int num_lines, int stride, + uint8_t *io_ptr, unsigned int num_io_bytes) +{ + Encoder *encoder = (Encoder *)lz; + uint8_t *io_ptr_end = io_ptr + num_io_bytes; + + encoder->type = type; + encoder->width = width; + encoder->height = height; + encoder->stride = stride; + + if (IS_IMAGE_TYPE_PLT[encoder->type]) { + if (encoder->stride > (width / PLT_PIXELS_PER_BYTE[encoder->type])) { + if (((width % PLT_PIXELS_PER_BYTE[encoder->type]) == 0) || ( + (encoder->stride - (width / PLT_PIXELS_PER_BYTE[encoder->type])) > 1)) { + encoder->usr->error(encoder->usr, "stride overflows (plt)\n"); + } + } + } else { + if (encoder->stride != width * RGB_BYTES_PER_PIXEL[encoder->type]) { + encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb) %d != %d * %d (%d)\n", + encoder->stride, width, RGB_BYTES_PER_PIXEL[encoder->type], + encoder->type); + } + } + + // assign the output buffer + if (!encoder_reset(encoder, io_ptr, io_ptr_end)) { + encoder->usr->error(encoder->usr, "lz encoder io reset failed\n"); + } + + // first read the list of the image segments + if (!lz_read_image_segments(encoder, lines, num_lines)) { + encoder->usr->error(encoder->usr, "lz encoder reading image segments failed\n"); + } + + encode_32(encoder, LZ_MAGIC); + encode_32(encoder, LZ_VERSION); + encode_32(encoder, type); + encode_32(encoder, width); + encode_32(encoder, height); + encode_32(encoder, stride); + encode_32(encoder, top_down); // TODO: maybe compress type and top_down to one byte + + switch (encoder->type) { + case LZ_IMAGE_TYPE_PLT1_BE: + case LZ_IMAGE_TYPE_PLT1_LE: + case LZ_IMAGE_TYPE_PLT4_BE: + case LZ_IMAGE_TYPE_PLT4_LE: + case LZ_IMAGE_TYPE_PLT8: + lz_plt_compress(encoder); + break; + case LZ_IMAGE_TYPE_RGB16: + lz_rgb16_compress(encoder); + break; + case LZ_IMAGE_TYPE_RGB24: + lz_rgb24_compress(encoder); + break; + case LZ_IMAGE_TYPE_RGB32: + lz_rgb32_compress(encoder); + break; + case LZ_IMAGE_TYPE_RGBA: + lz_rgb32_compress(encoder); + lz_rgb_alpha_compress(encoder); + break; + case LZ_IMAGE_TYPE_XXXA: + lz_rgb_alpha_compress(encoder); + break; + case LZ_IMAGE_TYPE_A8: + lz_a8_compress(encoder); + break; + case LZ_IMAGE_TYPE_INVALID: + default: + encoder->usr->error(encoder->usr, "bad image type\n"); + } + + // move all the used segments to the free ones + lz_reset_image_seg(encoder); + + encoder->io_bytes_count -= (encoder->io_end - encoder->io_now); + + return encoder->io_bytes_count; +} + +/* + initialize and read lz magic +*/ +void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes, + LzImageType *out_type, int *out_width, int *out_height, + int *out_n_pixels, int *out_top_down, const SpicePalette *palette) +{ + Encoder *encoder = (Encoder *)lz; + uint8_t *io_ptr_end = io_ptr + num_io_bytes; + uint32_t magic; + uint32_t version; + + if (!encoder_reset(encoder, io_ptr, io_ptr_end)) { + encoder->usr->error(encoder->usr, "io reset failed"); + } + + magic = decode_32(encoder); + if (magic != LZ_MAGIC) { + encoder->usr->error(encoder->usr, "bad magic\n"); + } + + version = decode_32(encoder); + if (version != LZ_VERSION) { + encoder->usr->error(encoder->usr, "bad version\n"); + } + + encoder->type = (LzImageType)decode_32(encoder); + encoder->width = decode_32(encoder); + encoder->height = decode_32(encoder); + encoder->stride = decode_32(encoder); + *out_top_down = decode_32(encoder); + + *out_width = encoder->width; + *out_height = encoder->height; +// *out_stride = encoder->stride; + *out_type = encoder->type; + + // TODO: maybe instead of stride we can encode out_n_pixels + // (if stride is not necessary in decoding). + if (IS_IMAGE_TYPE_PLT[encoder->type]) { + encoder->palette = palette; + *out_n_pixels = encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type] * encoder->height; + } else { + *out_n_pixels = encoder->width * encoder->height; + } +} + +void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf) +{ + Encoder *encoder = (Encoder *)lz; + size_t out_size = 0; + size_t alpha_size = 0; + size_t size = 0; + if (IS_IMAGE_TYPE_PLT[encoder->type]) { + if (to_type == encoder->type) { + size = encoder->height * encoder->stride; + out_size = lz_plt_decompress(encoder, (one_byte_pixel_t *)buf, size); + } else if (to_type == LZ_IMAGE_TYPE_RGB32) { + size = encoder->height * encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type]; + if (!encoder->palette) { + encoder->usr->error(encoder->usr, + "a palette is missing (for bpp to rgb decoding)\n"); + return; + } + switch (encoder->type) { + case LZ_IMAGE_TYPE_PLT1_BE: + out_size = lz_plt1_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + break; + case LZ_IMAGE_TYPE_PLT1_LE: + out_size = lz_plt1_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + break; + case LZ_IMAGE_TYPE_PLT4_BE: + out_size = lz_plt4_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + break; + case LZ_IMAGE_TYPE_PLT4_LE: + out_size = lz_plt4_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + break; + case LZ_IMAGE_TYPE_PLT8: + out_size = lz_plt8_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + break; + case LZ_IMAGE_TYPE_RGB16: + case LZ_IMAGE_TYPE_RGB24: + case LZ_IMAGE_TYPE_RGB32: + case LZ_IMAGE_TYPE_RGBA: + case LZ_IMAGE_TYPE_XXXA: + case LZ_IMAGE_TYPE_INVALID: + default: + encoder->usr->error(encoder->usr, "bad image type\n"); + } + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + } else { + size = encoder->height * encoder->width; + switch (encoder->type) { + case LZ_IMAGE_TYPE_RGB16: + if (encoder->type == to_type) { + out_size = lz_rgb16_decompress(encoder, (rgb16_pixel_t *)buf, size); + } else if (to_type == LZ_IMAGE_TYPE_RGB32) { + out_size = lz_rgb16_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_RGB24: + if (encoder->type == to_type) { + out_size = lz_rgb24_decompress(encoder, (rgb24_pixel_t *)buf, size); + } else if (to_type == LZ_IMAGE_TYPE_RGB32) { + out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_RGB32: + if (encoder->type == to_type) { + out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_RGBA: + if (encoder->type == to_type) { + out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size); + spice_assert(alpha_size == size); + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_XXXA: + if (encoder->type == to_type) { + alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size); + out_size = alpha_size; + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_A8: + if (encoder->type == to_type) { + alpha_size = lz_a8_decompress(encoder, (one_byte_pixel_t *)buf, size); + out_size = alpha_size; + } else if (to_type == LZ_IMAGE_TYPE_RGB32) { + alpha_size = lz_a8_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); + out_size = alpha_size; + } else { + encoder->usr->error(encoder->usr, "unsupported output format\n"); + } + break; + case LZ_IMAGE_TYPE_PLT1_LE: + case LZ_IMAGE_TYPE_PLT1_BE: + case LZ_IMAGE_TYPE_PLT4_LE: + case LZ_IMAGE_TYPE_PLT4_BE: + case LZ_IMAGE_TYPE_PLT8: + case LZ_IMAGE_TYPE_INVALID: + default: + encoder->usr->error(encoder->usr, "bad image type\n"); + } + } + + spice_assert(is_io_to_decode_end(encoder)); + spice_assert(out_size == size); + + if (out_size != size) { + encoder->usr->error(encoder->usr, "bad decode size\n"); + } +} diff --git a/spice-common/common/lz.h b/spice-common/common/lz.h new file mode 100644 index 0000000..21ba1fa --- /dev/null +++ b/spice-common/common/lz.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + dictionary compression for images based on fastlz (http://www.fastlz.org/) + (Distributed under MIT license). +*/ +#ifndef __LZ_H +#define __LZ_H + +#include + +#include "lz_common.h" +#include "lz_config.h" +#include "draw.h" +#include "macros.h" + +SPICE_BEGIN_DECLS + +typedef void *LzContext; + +typedef struct LzUsrContext LzUsrContext; +struct LzUsrContext { + SPICE_ATTR_PRINTF(2, 3) void (*error)(LzUsrContext *usr, const char *fmt, ...); + SPICE_ATTR_PRINTF(2, 3) void (*warn)(LzUsrContext *usr, const char *fmt, ...); + SPICE_ATTR_PRINTF(2, 3) void (*info)(LzUsrContext *usr, const char *fmt, ...); + void *(*malloc)(LzUsrContext *usr, int size); + void (*free)(LzUsrContext *usr, void *ptr); + int (*more_space)(LzUsrContext *usr, uint8_t **io_ptr); // get the next chunk of the + // compressed buffer. return + // number of bytes in the chunk. + int (*more_lines)(LzUsrContext *usr, uint8_t **lines); // get the next chunk of the + // original image. If the image + // is down to top, return it from + // the last line to the first one + // (stride should always be + // positive) +}; + +/* + assumes width is in pixels and stride is in bytes + return: the number of bytes in the compressed data + + TODO : determine size limit for the first segment and each chunk. check validity + of the segment or go to literal copy. + TODO : currently support only rgb images in which width*bytes_per_pixel = stride OR + palette images in which stride equals the min number of bytes to + hold a line. stride is not necessary for now. just for sanity check. + stride should be > 0 +*/ +int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down, + uint8_t *lines, unsigned int num_lines, int stride, + uint8_t *io_ptr, unsigned int num_io_bytes); + +/* + prepare encoder and read lz magic. + out_n_pixels number of compressed pixels. May differ from Width*height in plt1/4. + Use it for allocation the decompressed buffer. + +*/ +void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes, + LzImageType *out_type, int *out_width, int *out_height, + int *out_n_pixels, int *out_top_down, const SpicePalette *palette); + +/* + to_type = the image output type. + We assume the buffer is consecutive. i.e. width = stride + + Important: if the image is plt1/4 and to_type is rgb32, the image + will decompressed including the last bits in each line. This means buffer should be + larger than width*height if needed and you should use stride to fix it. + Note: If the image is down to top, set the stride in the sw surface to negative. + use alloc_lz_image_surface create the surface. +*/ +void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf); + +LzContext *lz_create(LzUsrContext *usr); + +void lz_destroy(LzContext *lz); + +SPICE_END_DECLS + +#endif // __LZ_H diff --git a/spice-common/common/lz_common.h b/spice-common/common/lz_common.h new file mode 100644 index 0000000..78df003 --- /dev/null +++ b/spice-common/common/lz_common.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/*common header for encoder and decoder*/ + +#ifndef _LZ_COMMON_H +#define _LZ_COMMON_H + +#include +#include "verify.h" + +SPICE_BEGIN_DECLS + +//#define DEBUG + +/* change the max window size will require change in the encoding format*/ +#define LZ_MAX_WINDOW_SIZE (1 << 25) +#define MAX_COPY 32 + +typedef enum { + LZ_IMAGE_TYPE_INVALID, + LZ_IMAGE_TYPE_PLT1_LE, + LZ_IMAGE_TYPE_PLT1_BE, // PLT stands for palette + LZ_IMAGE_TYPE_PLT4_LE, + LZ_IMAGE_TYPE_PLT4_BE, + LZ_IMAGE_TYPE_PLT8, + LZ_IMAGE_TYPE_RGB16, + LZ_IMAGE_TYPE_RGB24, + LZ_IMAGE_TYPE_RGB32, + LZ_IMAGE_TYPE_RGBA, + LZ_IMAGE_TYPE_XXXA, + LZ_IMAGE_TYPE_A8 +} LzImageType; + +#define LZ_IMAGE_TYPE_MASK 0x0f +#define LZ_IMAGE_TYPE_LOG 4 // number of bits required for coding the image type + +/* access to the arrays is based on the image types */ +static const int IS_IMAGE_TYPE_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; +static const int IS_IMAGE_TYPE_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; +static const int PLT_PIXELS_PER_BYTE[] = {0, 8, 8, 2, 2, 1}; +static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 1}; + +verify(SPICE_N_ELEMENTS(IS_IMAGE_TYPE_PLT) == (LZ_IMAGE_TYPE_A8 + 1)); +verify(SPICE_N_ELEMENTS(IS_IMAGE_TYPE_RGB) == (LZ_IMAGE_TYPE_A8 + 1)); +verify(SPICE_N_ELEMENTS(PLT_PIXELS_PER_BYTE) == (LZ_IMAGE_TYPE_PLT8 + 1)); +verify(SPICE_N_ELEMENTS(RGB_BYTES_PER_PIXEL) == (LZ_IMAGE_TYPE_A8 + 1)); + +/* ASCII "LZ " */ +#define LZ_MAGIC 0x20205a4c +#define LZ_VERSION_MAJOR 1U +#define LZ_VERSION_MINOR 1U +#define LZ_VERSION ((LZ_VERSION_MAJOR << 16) | (LZ_VERSION_MINOR & 0xffff)) + +SPICE_END_DECLS + +#endif // _LZ_COMMON_H diff --git a/spice-common/common/lz_compress_tmpl.c b/spice-common/common/lz_compress_tmpl.c new file mode 100644 index 0000000..0305278 --- /dev/null +++ b/spice-common/common/lz_compress_tmpl.c @@ -0,0 +1,540 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + + Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + This file incorporates work covered by the following copyright and + permission notice: + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + 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. + +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#define DJB2_START 5381 +#define DJB2_HASH(hash, c) (hash = ((hash << 5) + hash) ^ (c)) //|{hash = ((hash << 5) + hash) + c;} + +/* + For each pixel type the following macros are defined: + PIXEL : input type + FNAME(name) + ENCODE_PIXEL(encoder, pixel) : writing a pixel to the compressed buffer (byte by byte) + SAME_PIXEL(pix1, pix2) : comparing two pixels + HASH_FUNC(value, pix_ptr) : hash func of 3 consecutive pixels +*/ + +#ifdef LZ_PLT +#define PIXEL one_byte_pixel_t +#define FNAME(name) lz_plt_##name +#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes + // from the pixel +#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a) +#define HASH_FUNC(v, p) { \ + v = DJB2_START; \ + DJB2_HASH(v, p[0].a); \ + DJB2_HASH(v, p[1].a); \ + DJB2_HASH(v, p[2].a); \ + v &= HASH_MASK; \ + } +#endif + +#ifdef LZ_A8 +#define PIXEL one_byte_pixel_t +#define FNAME(name) lz_a8_##name +#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes + // from the pixel +#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a) +#define HASH_FUNC(v, p) { \ + v = DJB2_START; \ + DJB2_HASH(v, p[0].a); \ + DJB2_HASH(v, p[1].a); \ + DJB2_HASH(v, p[2].a); \ + v &= HASH_MASK; \ + } +#endif + +#ifdef LZ_RGB_ALPHA +//#undef LZ_RGB_ALPHA +#define PIXEL rgb32_pixel_t +#define FNAME(name) lz_rgb_alpha_##name +#define ENCODE_PIXEL(e, pix) {encode(e, (pix).pad);} +#define SAME_PIXEL(pix1, pix2) ((pix1).pad == (pix2).pad) +#define HASH_FUNC(v, p) { \ + v = DJB2_START; \ + DJB2_HASH(v, p[0].pad); \ + DJB2_HASH(v, p[1].pad); \ + DJB2_HASH(v, p[2].pad); \ + v &= HASH_MASK; \ + } +#endif + + +#ifdef LZ_RGB16 +#define PIXEL rgb16_pixel_t +#define FNAME(name) lz_rgb16_##name +#define GET_r(pix) (((pix) >> 10) & 0x1f) +#define GET_g(pix) (((pix) >> 5) & 0x1f) +#define GET_b(pix) ((pix) & 0x1f) +#define ENCODE_PIXEL(e, pix) {encode(e, (pix) >> 8); encode(e, (pix) & 0xff);} + +#define HASH_FUNC(v, p) { \ + v = DJB2_START; \ + DJB2_HASH(v, p[0] & (0x00ff)); \ + DJB2_HASH(v, (p[0] >> 8) & (0x007f)); \ + DJB2_HASH(v, p[1]&(0x00ff)); \ + DJB2_HASH(v, (p[1] >> 8) & (0x007f)); \ + DJB2_HASH(v, p[2] & (0x00ff)); \ + DJB2_HASH(v, (p[2] >> 8) & (0x007f)); \ + v &= HASH_MASK; \ +} +#endif + +#ifdef LZ_RGB24 +#define PIXEL rgb24_pixel_t +#define FNAME(name) lz_rgb24_##name +#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} +#endif + +#ifdef LZ_RGB32 +#define PIXEL rgb32_pixel_t +#define FNAME(name) lz_rgb32_##name +#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} +#endif + + +#if defined(LZ_RGB24) || defined(LZ_RGB32) +#define GET_r(pix) ((pix).r) +#define GET_g(pix) ((pix).g) +#define GET_b(pix) ((pix).b) +#define HASH_FUNC(v, p) { \ + v = DJB2_START; \ + DJB2_HASH(v, p[0].r); \ + DJB2_HASH(v, p[0].g); \ + DJB2_HASH(v, p[0].b); \ + DJB2_HASH(v, p[1].r); \ + DJB2_HASH(v, p[1].g); \ + DJB2_HASH(v, p[1].b); \ + DJB2_HASH(v, p[2].r); \ + DJB2_HASH(v, p[2].g); \ + DJB2_HASH(v, p[2].b); \ + v &= HASH_MASK; \ + } +#endif + +#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) +#define SAME_PIXEL(p1, p2) (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \ + GET_b(p1) == GET_b(p2)) + +#endif + +#define PIXEL_ID(pix_ptr, seg_ptr) (pix_ptr - ((PIXEL *)seg_ptr->lines) + seg_ptr->size_delta) + +// when encoding, the ref can be in previous segment, and we should check that it doesn't +// exceeds its bounds. +// TODO: optimization: when only one chunk exists or when the reference is in the same segment, +// don't make checks if we reach end of segments +// TODO: optimize to continue match between segments? +// TODO: check hash function +// TODO: check times + +/* compresses one segment starting from 'from'.*/ +static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *from, int copied) +{ + const PIXEL *ip = from; + const PIXEL *ip_bound = (PIXEL *)(seg->lines_end) - BOUND_OFFSET; + const PIXEL *ip_limit = (PIXEL *)(seg->lines_end) - LIMIT_OFFSET; + HashEntry *hslot; + int hval; + int copy = copied; + + if (copy == 0) { + encode_copy_count(encoder, MAX_COPY - 1); + } + + + while (LZ_EXPECT_CONDITIONAL(ip < ip_limit)) { // TODO: maybe change ip_limit and enabling + // moving to the next seg + const PIXEL *ref; + const PIXEL *ref_limit; + size_t distance; + + /* minimum match length */ +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8) + size_t len = 3; +#elif defined(LZ_RGB16) + size_t len = 2; +#else + size_t len = 1; +#endif + /* comparison starting-point */ + const PIXEL *anchor = ip; + + + + // TODO: RLE without checking if not first byte. + // TODO: optimize comparisons + + /* check for a run */ // TODO for RGB we can use less pixels + if (LZ_EXPECT_CONDITIONAL(ip > (PIXEL *)(seg->lines))) { + if (SAME_PIXEL(ip[-1], ip[0]) && SAME_PIXEL(ip[0], ip[1]) && SAME_PIXEL(ip[1], ip[2])) { + distance = 1; + ip += 3; + ref = anchor + 2; + ref_limit = (PIXEL *)(seg->lines_end); + + goto match; + } + } + + /* find potential match */ + HASH_FUNC(hval, ip); + hslot = encoder->htab + hval; + ref = (PIXEL *)(hslot->ref); + ref_limit = (PIXEL *)(hslot->image_seg->lines_end); + + /* calculate distance to the match */ + distance = PIXEL_ID(anchor, seg) - PIXEL_ID(ref, hslot->image_seg); + + /* update hash table */ + hslot->image_seg = seg; + hslot->ref = (uint8_t *)anchor; + + /* is this a match? check the first 3 pixels */ + if (distance == 0 || (distance >= MAX_FARDISTANCE)) { + goto literal; + } + /* check if the hval key identical*/ + // no need to check ref limit here because the word size in the htab is 3 pixels + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + goto literal; + } + ref++; + ip++; + + /* minimum match length for rgb16 is 2 and for plt and alpha is 3 */ +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_RGB16) || defined(LZ_A8) + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + goto literal; + } + ref++; + ip++; +#endif + +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8) + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + goto literal; + } + ref++; + ip++; +#endif + /* far, needs at least 5-byte match */ + if (distance >= MAX_DISTANCE) { +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8) + if (ref >= (ref_limit - 1)) { + goto literal; + } +#else + if (ref > (ref_limit - 1)) { + goto literal; + } +#endif + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + goto literal; + } + ref++; + ip++; + len++; +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8) + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + goto literal; + } + ref++; + ip++; + len++; +#endif + } +match: // RLE or dictionary (both are encoded by distance from ref (-1) and length) + + /* distance is biased */ + distance--; + + // ip is located now at the position of the second mismatch. + // later it will be subtracted by 3 + + if (!distance) { + /* zero distance means a run */ + PIXEL x = *ref; + while ((ip < ip_bound) && (ref < ref_limit)) { // TODO: maybe separate a run from + // the same seg or from different + // ones in order to spare + // ref < ref_limit + if (!SAME_PIXEL(*ref, x)) { + ref++; + break; + } else { + ref++; + ip++; + } + } + } else { + // TODO: maybe separate a run from the same seg or from different ones in order + // to spare ref < ref_limit and that way we can also perform 8 calls of + // (ref++ != ip++) outside a loop + while ((ip < ip_bound) && (ref < ref_limit)) { + if (!SAME_PIXEL(*ref, *ip)) { + ref++; + ip++; + break; + } else { + ref++; + ip++; + } + } + } + + /* if we have copied something, adjust the copy count */ + if (copy) { + /* copy is biased, '0' means 1 byte copy */ + update_copy_count(encoder, copy - 1); + } else { + /* back, to overwrite the copy count */ + compress_output_prev(encoder); + } + + /* reset literal counter */ + copy = 0; + + /* length is biased, '1' means a match of 3 pixels for PLT and alpha*/ + /* for RGB 16 1 means 2 */ + /* for RGB24/32 1 means 1...*/ + ip -= 3; + len = ip - anchor; +#if defined(LZ_RGB16) + len++; +#elif defined(LZ_RGB24) || defined(LZ_RGB32) + len += 2; +#endif + /* encode the match (like fastlz level 2)*/ + if (distance < MAX_DISTANCE) { // MAX_DISTANCE is 2^13 - 1 + // when copy is performed, the byte that holds the copy count is smaller than 32. + // When there is a reference, the first byte is always larger then 32 + + // 3 bits = length, 5 bits = 5 MSB of distance, 8 bits = 8 LSB of distance + if (len < 7) { + encode(encoder, (uint8_t)((len << 5) + (distance >> 8))); + encode(encoder, (uint8_t)(distance & 255)); + } else { // more than 3 bits are needed for length + // 3 bits 7, 5 bits = 5 MSB of distance, next bytes are 255 till we + // receive a smaller number, last byte = 8 LSB of distance + encode(encoder, (uint8_t)((7 << 5) + (distance >> 8))); + for (len -= 7; len >= 255; len -= 255) { + encode(encoder, 255); + } + encode(encoder, (uint8_t)len); + encode(encoder, (uint8_t)(distance & 255)); + } + } else { + /* far away */ + if (len < 7) { // the max_far_distance is ~2^16+2^13 so two more bytes are needed + // 3 bits = length, 5 bits = 5 MSB of MAX_DISTANCE, 8 bits = 8 LSB of MAX_DISTANCE, + // 8 bits = 8 MSB distance-MAX_distance (smaller than 2^16),8 bits=8 LSB of + // distance-MAX_distance + distance -= MAX_DISTANCE; + encode(encoder, (uint8_t)((len << 5) + 31)); + encode(encoder, (uint8_t)255); + encode(encoder, (uint8_t)(distance >> 8)); + encode(encoder, (uint8_t)(distance & 255)); + } else { + // same as before, but the first byte is followed by the left overs of len + distance -= MAX_DISTANCE; + encode(encoder, (uint8_t)((7 << 5) + 31)); + for (len -= 7; len >= 255; len -= 255) { + encode(encoder, 255); + } + encode(encoder, (uint8_t)len); + encode(encoder, 255); + encode(encoder, (uint8_t)(distance >> 8)); + encode(encoder, (uint8_t)(distance & 255)); + } + } + + /* update the hash at match boundary */ +#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) + if (ip > anchor) { +#endif + HASH_FUNC(hval, ip); + encoder->htab[hval].ref = (uint8_t *)ip; + ip++; + encoder->htab[hval].image_seg = seg; +#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) + } else {ip++; + } +#endif +#if defined(LZ_RGB24) || defined(LZ_RGB32) + if (ip > anchor) { +#endif + HASH_FUNC(hval, ip); + encoder->htab[hval].ref = (uint8_t *)ip; + ip++; + encoder->htab[hval].image_seg = seg; +#if defined(LZ_RGB24) || defined(LZ_RGB32) + } else {ip++; + } +#endif + /* assuming literal copy */ + encode_copy_count(encoder, MAX_COPY - 1); + continue; + +literal: + ENCODE_PIXEL(encoder, *anchor); + anchor++; + ip = anchor; + copy++; + + if (LZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) { + copy = 0; + encode_copy_count(encoder, MAX_COPY - 1); + } + } // END LOOP (ip < ip_limit) + + + /* left-over as literal copy */ + ip_bound++; + while (ip <= ip_bound) { + ENCODE_PIXEL(encoder, *ip); + ip++; + copy++; + if (copy == MAX_COPY) { + copy = 0; + encode_copy_count(encoder, MAX_COPY - 1); + } + } + + /* if we have copied something, adjust the copy length */ + if (copy) { + update_copy_count(encoder, copy - 1); + } else { + compress_output_prev(encoder); // in case we created a new buffer for copy, check that + // red_worker could handle size that do not contain the + // ne buffer + } +} + + +/* initializes the hash table. if the file is very small, copies it. + copies the first two pixels of the first segment, and sends the segments + one by one to compress_seg. + the number of bytes compressed are stored inside encoder. + */ +static void FNAME(compress)(Encoder *encoder) +{ + LzImageSegment *cur_seg = encoder->head_image_segs; + HashEntry *hslot; + PIXEL *ip; + + // fetch the first image segment that is not too small + while (cur_seg && ((((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) < 4)) { + // coping the segment + if (cur_seg->lines != cur_seg->lines_end) { + ip = (PIXEL *)cur_seg->lines; + // Note: we assume MAX_COPY > 3 + encode_copy_count(encoder, (uint8_t)( + (((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) - 1)); + while (ip < (PIXEL *)cur_seg->lines_end) { + ENCODE_PIXEL(encoder, *ip); + ip++; + } + } + cur_seg = cur_seg->next; + } + + if (!cur_seg) { + return; + } + + ip = (PIXEL *)cur_seg->lines; + + /* initialize hash table */ + for (hslot = encoder->htab; hslot < encoder->htab + HASH_SIZE; hslot++) { + hslot->ref = (uint8_t*)ip; + hslot->image_seg = cur_seg; + } + + encode_copy_count(encoder, MAX_COPY - 1); + ENCODE_PIXEL(encoder, *ip); + ip++; + ENCODE_PIXEL(encoder, *ip); + ip++; + + // compressing the first segment + FNAME(compress_seg)(encoder, cur_seg, ip, 2); + + // compressing the next segments + for (cur_seg = cur_seg->next; cur_seg; cur_seg = cur_seg->next) { + FNAME(compress_seg)(encoder, cur_seg, (PIXEL *)cur_seg->lines, 0); + } +} + +#undef FNAME +#undef PIXEL_ID +#undef PIXEL +#undef ENCODE_PIXEL +#undef SAME_PIXEL +#undef LZ_READU16 +#undef HASH_FUNC +#undef BYTES_TO_16 +#undef HASH_FUNC_16 +#undef GET_r +#undef GET_g +#undef GET_b +#undef GET_CODE +#undef LZ_PLT +#undef LZ_RGB_ALPHA +#undef LZ_RGB16 +#undef LZ_RGB24 +#undef LZ_RGB32 +#undef LZ_A8 +#undef HASH_FUNC2 diff --git a/spice-common/common/lz_config.h b/spice-common/common/lz_config.h new file mode 100644 index 0000000..d8675a8 --- /dev/null +++ b/spice-common/common/lz_config.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __LZ_CONFIG_H +#define __LZ_CONFIG_H + +#include +#include + +#ifdef __GNUC__ +#include +#else +#ifdef QXLDD +#include +#include "os_dep.h" +#else +#include +#include +#endif // QXLDD +#endif //__GNUC__ + +#endif //__LZ_CONFIG_H diff --git a/spice-common/common/lz_decompress_tmpl.c b/spice-common/common/lz_decompress_tmpl.c new file mode 100644 index 0000000..04a5121 --- /dev/null +++ b/spice-common/common/lz_decompress_tmpl.c @@ -0,0 +1,343 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + + Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . + + This file incorporates work covered by the following copyright and + permission notice: + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + 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. + +*/ + +// External defines: PLT, RGBX/PLTXX/ALPHA, TO_RGB32. +// If PLT4/1 and TO_RGB32 are defined, we need CAST_PLT_DISTANCE (because then the number of +// pixels differ from the units used in the compression) + +/* + For each output pixel type the following macros are defined: + OUT_PIXEL - the output pixel type + COPY_PIXEL(p, out) - assigns the pixel to the place pointed by out and increases + out. Used in RLE. Need special handling because in alpha we + copy only the pad byte. + COPY_REF_PIXEL(ref, out) - copies the pixel pointed by ref to the pixel pointed by out. + Increases ref and out. + COPY_COMP_PIXEL(encoder, out) - copies pixel from the compressed buffer to the decompressed + buffer. Increases out. +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined(LZ_RGB_ALPHA) +#define COPY_PIXEL(p, out) (*out++ = p) +#define COPY_REF_PIXEL(ref, out) (*out++ = *ref++) +#endif + + +// decompressing plt to plt +#ifdef LZ_PLT +#ifndef TO_RGB32 +#define OUT_PIXEL one_byte_pixel_t +#define FNAME(name) lz_plt_##name +#define COPY_COMP_PIXEL(encoder, out) {out->a = decode(encoder); out++;} +#else // TO_RGB32 +#define OUT_PIXEL rgb32_pixel_t +#define COPY_PLT_ENTRY(ent, out) { \ + (out)->b = ent; \ + (out)->g = (ent >> 8); \ + (out)->r = (ent >> 16); \ + (out)->pad = 0; \ +} +#ifdef PLT8 +#define FNAME(name) lz_plt8_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out) { \ + uint32_t rgb = encoder->palette->ents[decode(encoder)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++;} +#elif defined(PLT4_BE) +#define FNAME(name) lz_plt4_be_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out){ \ + uint8_t byte = decode(encoder); \ + uint32_t rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ + rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ +} +#define CAST_PLT_DISTANCE(dist) (dist*2) +#elif defined(PLT4_LE) +#define FNAME(name) lz_plt4_le_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out){ \ + uint8_t byte = decode(encoder); \ + uint32_t rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ + rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ +} +#define CAST_PLT_DISTANCE(dist) (dist*2) +#elif defined(PLT1_BE) // TODO store palette entries for direct access +#define FNAME(name) lz_plt1_be_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out){ \ + uint8_t byte = decode(encoder); \ + int i; \ + uint32_t fore = encoder->palette->ents[1]; \ + uint32_t back = encoder->palette->ents[0]; \ + for (i = 7; i >= 0; i--) \ + { \ + if ((byte >> i) & 1) { \ + COPY_PLT_ENTRY(fore, out); \ + } else { \ + COPY_PLT_ENTRY(back, out); \ + } \ + out++; \ + } \ +} +#define CAST_PLT_DISTANCE(dist) (dist*8) +#elif defined(PLT1_LE) +#define FNAME(name) lz_plt1_le_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out){ \ + uint8_t byte = decode(encoder); \ + int i; \ + uint32_t fore = encoder->palette->ents[1]; \ + uint32_t back = encoder->palette->ents[0]; \ + for (i = 0; i < 8; i++) \ + { \ + if ((byte >> i) & 1) { \ + COPY_PLT_ENTRY(fore, out); \ + } else { \ + COPY_PLT_ENTRY(back, out); \ + } \ + out++; \ + } \ +} +#define CAST_PLT_DISTANCE(dist) (dist*8) +#endif // PLT Type +#endif // TO_RGB32 +#endif + +#ifdef LZ_A8 +#ifndef TO_RGB32 +#define OUT_PIXEL one_byte_pixel_t +#define FNAME(name) lz_a8_##name +#define COPY_COMP_PIXEL(encoder, out) {out->a = decode(encoder); out++;} +#else // TO_RGB32 +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) lz_a8_to_rgb32_##name +#define COPY_COMP_PIXEL(encoder, out) { \ + (out)->b = (out)->g = (out)->r = 0; \ + (out)->pad = decode(encoder); \ + (out)++; \ + } +#endif +#endif + +#ifdef LZ_RGB16 +#ifndef TO_RGB32 +#define OUT_PIXEL rgb16_pixel_t +#define FNAME(name) lz_rgb16_##name +#define COPY_COMP_PIXEL(e, out) {*out = ((decode(e) << 8) | decode(e)); out++;} +#else +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) lz_rgb16_to_rgb32_##name +#define COPY_COMP_PIXEL(e, out) { \ + out->r = decode(e); \ + out->b = decode(e); \ + out->g = (((out->r) << 6) | ((out->b) >> 2)) & ~0x07; \ + out->g |= (out->g >> 5); \ + out->r = ((out->r << 1) & ~0x07)| ((out->r >> 4) & 0x07); \ + out->b = (out->b << 3) | ((out->b >> 2) & 0x07); \ + out->pad = 0; \ + out++; \ +} +#endif +#endif + +#ifdef LZ_RGB24 +#define OUT_PIXEL rgb24_pixel_t +#define FNAME(name) lz_rgb24_##name +#define COPY_COMP_PIXEL(e, out) {out->b = decode(e); out->g = decode(e); out->r = decode(e); out++;} +#endif + +#ifdef LZ_RGB32 +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) lz_rgb32_##name +#define COPY_COMP_PIXEL(e, out) { \ + out->b = decode(e); \ + out->g = decode(e); \ + out->r = decode(e); \ + out->pad = 0; \ + out++; \ +} +#endif + +#ifdef LZ_RGB_ALPHA +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) lz_rgb_alpha_##name +#define COPY_PIXEL(p, out) {out->pad = p.pad; out++;} +#define COPY_REF_PIXEL(ref, out) {out->pad = ref->pad; out++; ref++;} +#define COPY_COMP_PIXEL(e, out) {out->pad = decode(e); out++;} +#endif + +// return num of bytes in out_buf +static size_t FNAME(decompress)(Encoder *encoder, OUT_PIXEL *out_buf, int size) +{ + OUT_PIXEL *op = out_buf; + OUT_PIXEL *op_limit = out_buf + size; + uint32_t ctrl = decode(encoder); + int loop = TRUE; + + do { + const OUT_PIXEL *ref = op; + uint32_t len = ctrl >> 5; + uint32_t ofs = (ctrl & 31) << 8; // 5 MSb of distance + + if (ctrl >= MAX_COPY) { // reference (dictionary/RLE) + /* retrieving the reference and the match length */ + + uint8_t code; + len--; + //ref -= ofs; + if (len == 7 - 1) { // match length is bigger than 7 + do { + code = decode(encoder); + len += code; + } while (code == 255); // remaining of len + } + code = decode(encoder); + ofs += code; + + /* match from 16-bit distance */ + if (LZ_UNEXPECT_CONDITIONAL(code == 255)) { + if (LZ_EXPECT_CONDITIONAL((ofs - code) == (31 << 8))) { + ofs = decode(encoder) << 8; + ofs += decode(encoder); + ofs += MAX_DISTANCE; + } + } + +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_A8) + len += 3; // length is biased by 2 + 1 (fixing bias) +#elif defined(LZ_RGB16) + len += 2; // length is biased by 1 + 1 (fixing bias) +#else + len += 1; +#endif + ofs += 1; // offset is biased by 1 (fixing bias) + +#if defined(TO_RGB32) +#if defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || defined(PLT1_LE) + ofs = CAST_PLT_DISTANCE(ofs); + len = CAST_PLT_DISTANCE(len); +#endif +#endif + ref -= ofs; + + spice_assert(op + len <= op_limit); + spice_assert(ref + len <= op_limit); + spice_assert(ref >= out_buf); + + // TODO: optimize by not calling loop at least 3 times when not PLT_TO_RGB32 (len is + // always >=3). in PLT_TO_RGB32 len >= 3*number_of_pixels_per_byte + + /* copying the match*/ + + if (ref == (op - 1)) { // run // TODO: this will never be called in PLT4/1_TO_RGB + // because the number of pixel copied is larger + // then one... + /* optimize copy for a run */ + OUT_PIXEL b = *ref; + for (; len; --len) { + COPY_PIXEL(b, op); + spice_assert(op <= op_limit); + } + } else { + for (; len; --len) { + COPY_REF_PIXEL(ref, op); + spice_assert(op <= op_limit); + } + } + } else { // copy + ctrl++; // copy count is biased by 1 +#if defined(TO_RGB32) && (defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || \ + defined(PLT1_LE)) + spice_assert(op + CAST_PLT_DISTANCE(ctrl) <= op_limit); +#else + spice_assert(op + ctrl <= op_limit); +#endif + COPY_COMP_PIXEL(encoder, op); + + spice_assert(op <= op_limit); + + for (--ctrl; ctrl; ctrl--) { + COPY_COMP_PIXEL(encoder, op); + spice_assert(op <= op_limit); + } + } + + if (LZ_EXPECT_CONDITIONAL(op < op_limit)) { + ctrl = decode(encoder); + } else { + loop = FALSE; + } + } while (LZ_EXPECT_CONDITIONAL(loop)); + + return (op - out_buf); +} + +#undef LZ_PLT +#undef PLT8 +#undef PLT4_BE +#undef PLT4_LE +#undef PLT1_BE +#undef PLT1_LE +#undef LZ_RGB16 +#undef LZ_RGB24 +#undef LZ_RGB32 +#undef LZ_A8 +#undef LZ_RGB_ALPHA +#undef TO_RGB32 +#undef OUT_PIXEL +#undef FNAME +#undef COPY_PIXEL +#undef COPY_REF_PIXEL +#undef COPY_COMP_PIXEL +#undef COPY_PLT_ENTRY +#undef CAST_PLT_DISTANCE diff --git a/spice-common/common/macros.h b/spice-common/common/macros.h new file mode 100644 index 0000000..fe36929 --- /dev/null +++ b/spice-common/common/macros.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef __MACROS_H +#define __MACROS_H + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5) +#define SPICE_ATTR_NORETURN \ + __attribute__((noreturn)) +#define SPICE_ATTR_PRINTF(a,b) \ + __attribute__((format(printf,a,b))) +#else +#define SPICE_ATTR_NORETURN +#define SPICE_ATTR_PRINTF +#endif /* __GNUC__ */ + +#ifdef __GNUC__ +#define SPICE_CONSTRUCTOR_FUNC(func_name) \ + static void __attribute__((constructor)) func_name(void) +#define SPICE_DESTRUCTOR_FUNC(func_name) \ + static void __attribute__((destructor)) func_name(void) +#elif defined(_MSC_VER) +#define SPICE_CONSTRUCTOR_FUNC(func_name) \ + static void func_name(void); \ + static int func_name ## _wrapper(void) { func_name(); return 0; } \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) static int (* _array ## func_name)(void) = func_name ## _wrapper; \ + static void func_name(void) +#define SPICE_DESTRUCTOR_FUNC(func_name) \ + static void func_name(void); \ + static int func_name ## _wrapper(void) { func_name(); return 0; } \ + __pragma(section(".CRT$XPU",read)) \ + __declspec(allocate(".CRT$XPU")) static int (* _array ## func_name)(void) = func_name ## _wrapper; \ + static void func_name(void) +#else +#error Please implement SPICE_CONSTRUCTOR_FUNC and SPICE_DESTRUCTOR_FUNC for this compiler +#endif + + +#endif /* __MACROS_H */ diff --git a/spice-common/common/marshaller.c b/spice-common/common/marshaller.c new file mode 100644 index 0000000..00a7123 --- /dev/null +++ b/spice-common/common/marshaller.c @@ -0,0 +1,650 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "log.h" +#include "marshaller.h" +#include "mem.h" +#include +#include +#include +#include +#include + +#ifdef WORDS_BIGENDIAN +#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v) +#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v) +#define write_int16(ptr,v) (*((int16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v))) +#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v))) +#define write_int32(ptr,v) (*((int32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v))) +#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v))) +#define write_int64(ptr,v) (*((int64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v))) +#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v))) +#else +#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v) +#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v) +#define write_int16(ptr,v) (*((int16_t *)(ptr)) = v) +#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = v) +#define write_int32(ptr,v) (*((int32_t *)(ptr)) = v) +#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = v) +#define write_int64(ptr,v) (*((int64_t *)(ptr)) = v) +#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = v) +#endif + +typedef struct { + uint8_t *data; + size_t len; + spice_marshaller_item_free_func free_data; + void *opaque; +} MarshallerItem; + +/* Try to fit in 4k page with 2*pointer-size overhead (next ptr and malloc size) */ +#define MARSHALLER_BUFFER_SIZE (4096 - sizeof(void *) * 2) + +typedef struct MarshallerBuffer MarshallerBuffer; +struct MarshallerBuffer { + MarshallerBuffer *next; + uint8_t data[MARSHALLER_BUFFER_SIZE]; +}; + +#define N_STATIC_ITEMS 4 + +typedef struct SpiceMarshallerData SpiceMarshallerData; + +typedef struct { + SpiceMarshaller *marshaller; + int item_nr; + int is_64bit; + size_t offset; +} MarshallerRef; + +struct SpiceMarshaller { + size_t total_size; + SpiceMarshallerData *data; + SpiceMarshaller *next; + + MarshallerRef pointer_ref; + + int n_items; + int items_size; /* number of items available in items */ + MarshallerItem *items; + + MarshallerItem static_items[N_STATIC_ITEMS]; + bool has_fd; + int fd; +}; + +struct SpiceMarshallerData { + size_t total_size; + size_t base; + SpiceMarshaller *marshallers; + SpiceMarshaller *last_marshaller; + + size_t current_buffer_position; + MarshallerBuffer *current_buffer; + MarshallerItem *current_buffer_item; + MarshallerBuffer *buffers; + + SpiceMarshaller static_marshaller; + MarshallerBuffer static_buffer; +}; + +static void spice_marshaller_init(SpiceMarshaller *m, + SpiceMarshallerData *data) +{ + m->data = data; + m->next = NULL; + m->total_size = 0; + m->pointer_ref.marshaller = NULL; + m->n_items = 0; + m->items_size = N_STATIC_ITEMS; + m->items = m->static_items; + m->fd = -1; + m->has_fd = false; +} + +SpiceMarshaller *spice_marshaller_new(void) +{ + SpiceMarshallerData *d; + SpiceMarshaller *m; + + d = spice_new(SpiceMarshallerData, 1); + + d->last_marshaller = d->marshallers = &d->static_marshaller; + d->total_size = 0; + d->base = 0; + d->buffers = &d->static_buffer; + d->buffers->next = NULL; + d->current_buffer = d->buffers; + d->current_buffer_position = 0; + d->current_buffer_item = NULL; + + m = &d->static_marshaller; + spice_marshaller_init(m, d); + + return m; +} + +static void free_item_data(SpiceMarshaller *m) +{ + MarshallerItem *item; + int i; + + /* Free all user data */ + for (i = 0; i < m->n_items; i++) { + item = &m->items[i]; + if (item->free_data != NULL) { + item->free_data(item->data, item->opaque); + } + } +} + +static void free_items(SpiceMarshaller *m) +{ + if (m->items != m->static_items) { + free(m->items); + } +} + +void spice_marshaller_reset(SpiceMarshaller *m) +{ + SpiceMarshaller *m2, *next; + SpiceMarshallerData *d; + + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + for (m2 = m; m2 != NULL; m2 = next) { + next = m2->next; + free_item_data(m2); + + /* Free non-root marshallers */ + if (m2 != m) { + free_items(m2); + free(m2); + } + } + + m->next = NULL; + m->n_items = 0; + m->total_size = 0; + + d = m->data; + d->last_marshaller = d->marshallers; + d->total_size = 0; + d->base = 0; + d->current_buffer_item = NULL; + d->current_buffer = d->buffers; + d->current_buffer_position = 0; +} + +void spice_marshaller_destroy(SpiceMarshaller *m) +{ + MarshallerBuffer *buf, *next; + SpiceMarshallerData *d; + + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + spice_marshaller_reset(m); + + free_items(m); + + d = m->data; + + buf = d->buffers->next; + while (buf != NULL) { + next = buf->next; + free(buf); + buf = next; + } + + free(d); +} + +static MarshallerItem *spice_marshaller_add_item(SpiceMarshaller *m) +{ + MarshallerItem *item; + + if (m->n_items == m->items_size) { + int items_size = m->items_size * 2; + + if (m->items == m->static_items) { + m->items = spice_new(MarshallerItem, items_size); + memcpy(m->items, m->static_items, sizeof(MarshallerItem) * m->n_items); + } else { + m->items = spice_renew(MarshallerItem, m->items, items_size); + } + m->items_size = items_size; + } + item = &m->items[m->n_items++]; + item->free_data = NULL; + + return item; +} + +static size_t remaining_buffer_size(SpiceMarshallerData *d) +{ + return MARSHALLER_BUFFER_SIZE - d->current_buffer_position; +} + +uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size) +{ + MarshallerItem *item; + SpiceMarshallerData *d; + uint8_t *res; + + if (size == 0) { + return NULL; + } + + d = m->data; + + /* Check current item */ + item = &m->items[m->n_items - 1]; + if (item == d->current_buffer_item && + remaining_buffer_size(d) >= size) { + assert(m->n_items >= 1); + /* We can piggy back on existing item+buffer */ + res = item->data + item->len; + item->len += size; + d->current_buffer_position += size; + d->total_size += size; + m->total_size += size; + return res; + } + + item = spice_marshaller_add_item(m); + + if (remaining_buffer_size(d) >= size) { + /* Fits in current buffer */ + item->data = d->current_buffer->data + d->current_buffer_position; + item->len = size; + d->current_buffer_position += size; + d->current_buffer_item = item; + } else if (size > MARSHALLER_BUFFER_SIZE / 2) { + /* Large item, allocate by itself */ + item->data = (uint8_t *)spice_malloc(size); + item->len = size; + item->free_data = (spice_marshaller_item_free_func)free; + item->opaque = NULL; + } else { + /* Use next buffer */ + if (d->current_buffer->next == NULL) { + d->current_buffer->next = spice_new(MarshallerBuffer, 1); + d->current_buffer->next->next = NULL; + } + d->current_buffer = d->current_buffer->next; + d->current_buffer_position = size; + d->current_buffer_item = item; + item->data = d->current_buffer->data; + item->len = size; + } + + d->total_size += size; + m->total_size += size; + return item->data; +} + +void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size) +{ + MarshallerItem *item; + + if (size == 0) { + return; + } + + item = &m->items[m->n_items - 1]; + + assert(item->len >= size); + item->len -= size; +} + +uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size, + spice_marshaller_item_free_func free_data, void *opaque) +{ + MarshallerItem *item; + SpiceMarshallerData *d; + + if (data == NULL || size == 0) { + return NULL; + } + + item = spice_marshaller_add_item(m); + item->data = data; + item->len = size; + item->free_data = free_data; + item->opaque = opaque; + + d = m->data; + m->total_size += size; + d->total_size += size; + + return data; +} + +uint8_t *spice_marshaller_add(SpiceMarshaller *m, const uint8_t *data, size_t size) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, size); + memcpy(ptr, data, size); + return ptr; +} + +uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, const uint8_t *data, size_t size) +{ + /* the cast to no-const here is safe as data is used for writing only if + * free_data pointer is not NULL + */ + return spice_marshaller_add_ref_full(m, (uint8_t *) data, size, NULL, NULL); +} + +void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks) +{ + unsigned int i; + + for (i = 0; i < chunks->num_chunks; i++) { + spice_marshaller_add_ref(m, chunks->chunk[i].data, + chunks->chunk[i].len); + } +} + +SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m) +{ + SpiceMarshallerData *d; + SpiceMarshaller *m2; + + d = m->data; + + m2 = spice_new(SpiceMarshaller, 1); + spice_marshaller_init(m2, d); + + d->last_marshaller->next = m2; + d->last_marshaller = m2; + + return m2; +} + +SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit) +{ + SpiceMarshaller *m2; + uint8_t *p; + int size; + + size = is_64bit ? 8 : 4; + + p = spice_marshaller_reserve_space(m, size); + memset(p, 0, size); + m2 = spice_marshaller_get_submarshaller(m); + m2->pointer_ref.marshaller = m; + m2->pointer_ref.item_nr = m->n_items - 1; + m2->pointer_ref.offset = m->items[m->n_items - 1].len - size; + m2->pointer_ref.is_64bit = is_64bit; + + return m2; +} + +static uint8_t *lookup_ref(MarshallerRef *ref) +{ + MarshallerItem *item; + + item = &ref->marshaller->items[ref->item_nr]; + return item->data + ref->offset; +} + + +void spice_marshaller_set_base(SpiceMarshaller *m, size_t base) +{ + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + m->data->base = base; +} + +uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip_bytes, + size_t *len, int *free_res) +{ + MarshallerItem *item; + uint8_t *res, *p; + int i; + + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + if (m->n_items == 1 && m->next == NULL) { + *free_res = FALSE; + if (m->items[0].len <= skip_bytes) { + *len = 0; + return NULL; + } + *len = m->items[0].len - skip_bytes; + return m->items[0].data + skip_bytes; + } + + *free_res = TRUE; + res = (uint8_t *)spice_malloc(m->data->total_size - skip_bytes); + *len = m->data->total_size - skip_bytes; + p = res; + + do { + for (i = 0; i < m->n_items; i++) { + item = &m->items[i]; + + if (item->len <= skip_bytes) { + skip_bytes -= item->len; + continue; + } + memcpy(p, item->data + skip_bytes, item->len - skip_bytes); + p += item->len - skip_bytes; + skip_bytes = 0; + } + m = m->next; + } while (m != NULL); + + return res; +} + +uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m) +{ + return m->items[0].data; +} + +size_t spice_marshaller_get_offset(SpiceMarshaller *m) +{ + SpiceMarshaller *m2; + size_t offset; + + offset = 0; + m2 = m->data->marshallers; + while (m2 != m) { + offset += m2->total_size; + m2 = m2->next; + } + return offset - m->data->base; +} + +size_t spice_marshaller_get_size(SpiceMarshaller *m) +{ + return m->total_size; +} + +size_t spice_marshaller_get_total_size(SpiceMarshaller *m) +{ + return m->data->total_size; +} + +void spice_marshaller_flush(SpiceMarshaller *m) +{ + SpiceMarshaller *m2; + uint8_t *ptr_pos; + + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + for (m2 = m; m2 != NULL; m2 = m2->next) { + if (m2->pointer_ref.marshaller != NULL && m2->total_size > 0) { + ptr_pos = lookup_ref(&m2->pointer_ref); + if (m2->pointer_ref.is_64bit) { + write_uint64(ptr_pos, + spice_marshaller_get_offset(m2)); + } else { + write_uint32(ptr_pos, + spice_marshaller_get_offset(m2)); + } + } + } +} + +#ifndef WIN32 +int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec, + int n_vec, size_t skip_bytes) +{ + MarshallerItem *item; + int v, i; + + /* Only supported for root marshaller */ + assert(m->data->marshallers == m); + + v = 0; + do { + for (i = 0; i < m->n_items; i++) { + item = &m->items[i]; + + if (item->len <= skip_bytes) { + skip_bytes -= item->len; + continue; + } + if (v == n_vec) { + return v; /* Not enough space in vec */ + } + vec[v].iov_base = (uint8_t *)item->data + skip_bytes; + vec[v].iov_len = item->len - skip_bytes; + skip_bytes = 0; + v++; + } + m = m->next; + } while (m != NULL); + + return v; +} +#endif + +void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(uint64_t)); + write_uint64(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(int64_t)); + write_int64(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(uint32_t)); + write_uint32(ptr, v); + return (void *)ptr; +} + +void spice_marshaller_set_uint32(SPICE_GNUC_UNUSED SpiceMarshaller *m, void *ref, uint32_t v) +{ + write_uint32((uint8_t *)ref, v); +} + +void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(int32_t)); + write_int32(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(uint16_t)); + write_uint16(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(int16_t)); + write_int16(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(uint8_t)); + write_uint8(ptr, v); + return (void *)ptr; +} + +void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v) +{ + uint8_t *ptr; + + ptr = spice_marshaller_reserve_space(m, sizeof(int8_t)); + write_int8(ptr, v); + return (void *)ptr; +} + +void spice_marshaller_add_fd(SpiceMarshaller *m, int fd) +{ + spice_assert(m->has_fd == false); + + m->has_fd = true; + if (fd != -1) { + m->fd = dup(fd); + if (m->fd == -1) { + perror("dup"); + } + } else { + m->fd = -1; + } +} + +bool spice_marshaller_get_fd(SpiceMarshaller *m, int *fd) +{ + bool had_fd = m->has_fd; + + *fd = m->fd; + m->has_fd = false; + + return had_fd; +} diff --git a/spice-common/common/marshaller.h b/spice-common/common/marshaller.h new file mode 100644 index 0000000..316184e --- /dev/null +++ b/spice-common/common/marshaller.h @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_MARSHALLER +#define _H_MARSHALLER + +#include +#include +#include +#include "mem.h" +#ifndef WIN32 +#include +#endif + +SPICE_BEGIN_DECLS + +typedef struct SpiceMarshaller SpiceMarshaller; +typedef void (*spice_marshaller_item_free_func)(uint8_t *data, void *opaque); + +SpiceMarshaller *spice_marshaller_new(void); +void spice_marshaller_reset(SpiceMarshaller *m); +void spice_marshaller_destroy(SpiceMarshaller *m); +uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size); +void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size); +uint8_t *spice_marshaller_add(SpiceMarshaller *m, const uint8_t *data, size_t size); +uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, const uint8_t *data, size_t size); +uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size, + spice_marshaller_item_free_func free_data, void *opaque); +void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks); +void spice_marshaller_flush(SpiceMarshaller *m); +void spice_marshaller_set_base(SpiceMarshaller *m, size_t base); +uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip, + size_t *len, int *free_res); +uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m); +size_t spice_marshaller_get_offset(SpiceMarshaller *m); +size_t spice_marshaller_get_size(SpiceMarshaller *m); +size_t spice_marshaller_get_total_size(SpiceMarshaller *m); +SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m); +SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit); +#ifndef WIN32 +int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec, + int n_vec, size_t skip_bytes); +#endif +void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v); +void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v); +void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v); +void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v); +void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v); +void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v); +void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v); +void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v); + +void spice_marshaller_set_uint32(SpiceMarshaller *m, void *ref, uint32_t v); + +void spice_marshaller_add_fd(SpiceMarshaller *m, int fd); +bool spice_marshaller_get_fd(SpiceMarshaller *m, int *fd); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/mem.c b/spice-common/common/mem.c new file mode 100644 index 0000000..e430b5d --- /dev/null +++ b/spice-common/common/mem.c @@ -0,0 +1,296 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "spice_common.h" +#include "mem.h" + +#include + +#ifndef MALLOC_ERROR +#define MALLOC_ERROR(format, ...) SPICE_STMT_START { \ + spice_error(format, ## __VA_ARGS__); \ + abort(); \ +} SPICE_STMT_END +#endif + +size_t spice_strnlen(const char *str, size_t max_len) +{ + size_t len = 0; + + while (len < max_len && *str != 0) { + len++; + str++; + } + + return len; +} + +char *spice_strdup(const char *str) +{ + char *copy; + size_t len; + + if (str == NULL) { + return NULL; + } + + len = strlen(str) + 1; + copy = (char *)spice_malloc(len); + memcpy(copy, str, len); + return copy; +} + +char *spice_strndup(const char *str, size_t n_bytes) +{ + char *copy; + + if (str == NULL) { + return NULL; + } + + copy = (char *)spice_malloc(n_bytes + 1); + strncpy(copy, str, n_bytes); + copy[n_bytes] = 0; + return copy; +} + +void *spice_memdup(const void *mem, size_t n_bytes) +{ + void *copy; + + if (mem == NULL) { + return NULL; + } + + copy = spice_malloc(n_bytes); + memcpy(copy, mem, n_bytes); + return copy; +} + +void *spice_malloc(size_t n_bytes) +{ + void *mem; + + if (SPICE_LIKELY(n_bytes)) { + mem = malloc(n_bytes); + + if (SPICE_LIKELY(mem != NULL)) { + return mem; + } + + MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes); + } + return NULL; +} + +void *spice_malloc0(size_t n_bytes) +{ + void *mem; + + if (SPICE_LIKELY(n_bytes)) { + mem = calloc(1, n_bytes); + + if (SPICE_LIKELY(mem != NULL)) { + return mem; + } + + MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes); + } + return NULL; +} + +void *spice_realloc(void *mem, size_t n_bytes) +{ + if (SPICE_LIKELY(n_bytes)) { + mem = realloc(mem, n_bytes); + + if (SPICE_LIKELY(mem != NULL)) { + return mem; + } + + MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes); + } + + free(mem); + + return NULL; +} + +#define SIZE_OVERFLOWS(a,b) (SPICE_UNLIKELY ((a) > SIZE_MAX / (b))) + +void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) +{ + if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { + MALLOC_ERROR("overflow allocating %lu*%lu bytes", + (unsigned long)n_blocks, (unsigned long)n_block_bytes); + } + + return spice_malloc(n_blocks * n_block_bytes); +} + +void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) +{ + size_t size1, size2; + if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { + MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes", + (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size); + } + size1 = n_blocks * n_block_bytes; + size2 = size1 + extra_size; + if (size2 < size1) { + MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes", + (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size); + } + return spice_malloc(size2); +} + + +void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) +{ + if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { + MALLOC_ERROR("spice_malloc0_n: overflow allocating %lu*%lu bytes", + (unsigned long)n_blocks, (unsigned long)n_block_bytes); + } + + return spice_malloc0 (n_blocks * n_block_bytes); +} + +void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) +{ + if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { + MALLOC_ERROR("spice_realloc_n: overflow allocating %lu*%lu bytes", + (unsigned long)n_blocks, (unsigned long)n_block_bytes); + } + + return spice_realloc(mem, n_blocks * n_block_bytes); +} + +SpiceChunks *spice_chunks_new(uint32_t count) +{ + SpiceChunks *chunks; + + chunks = (SpiceChunks *)spice_malloc_n_m(count, sizeof(SpiceChunk), sizeof(SpiceChunks)); + chunks->flags = 0; + chunks->num_chunks = count; + + return chunks; +} + +SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) +{ + SpiceChunks *chunks; + + chunks = spice_chunks_new(1); + chunks->data_size = chunks->chunk[0].len = len; + chunks->chunk[0].data = data; + return chunks; +} + +void spice_chunks_destroy(SpiceChunks *chunks) +{ + unsigned int i; + + if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) { + for (i = 0; i < chunks->num_chunks; i++) { + free(chunks->chunk[i].data); + } + } + + free(chunks); +} + +void spice_chunks_linearize(SpiceChunks *chunks) +{ + uint8_t *data, *p; + unsigned int i; + + if (chunks->num_chunks > 1) { + data = (uint8_t*)spice_malloc(chunks->data_size); + for (p = data, i = 0; i < chunks->num_chunks; i++) { + memcpy(p, chunks->chunk[i].data, + chunks->chunk[i].len); + p += chunks->chunk[i].len; + } + if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) { + for (i = 0; i < chunks->num_chunks; i++) { + free(chunks->chunk[i].data); + } + } + chunks->num_chunks = 1; + chunks->flags |= SPICE_CHUNKS_FLAGS_FREE; + chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE; + chunks->chunk[0].data = data; + chunks->chunk[0].len = chunks->data_size; + } +} + +void spice_buffer_reserve(SpiceBuffer *buffer, size_t len) +{ + if ((buffer->capacity - buffer->offset) < len) { + buffer->capacity += (len + 1024); + buffer->buffer = (uint8_t*)spice_realloc(buffer->buffer, buffer->capacity); + } +} + +int spice_buffer_empty(SpiceBuffer *buffer) +{ + return buffer->offset == 0; +} + +uint8_t *spice_buffer_end(SpiceBuffer *buffer) +{ + return buffer->buffer + buffer->offset; +} + +void spice_buffer_reset(SpiceBuffer *buffer) +{ + buffer->offset = 0; +} + +void spice_buffer_free(SpiceBuffer *buffer) +{ + free(buffer->buffer); + buffer->offset = 0; + buffer->capacity = 0; + buffer->buffer = NULL; +} + +void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len) +{ + spice_buffer_reserve(buffer, len); + memcpy(buffer->buffer + buffer->offset, data, len); + buffer->offset += len; +} + +size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len) +{ + len = MIN(buffer->offset, len); + memcpy(dest, buffer->buffer, len); + return len; +} + +size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len) +{ + len = MIN(buffer->offset, len); + memmove(buffer->buffer, buffer->buffer + len, buffer->offset - len); + buffer->offset -= len; + return len; +} diff --git a/spice-common/common/mem.h b/spice-common/common/mem.h new file mode 100644 index 0000000..857e8b0 --- /dev/null +++ b/spice-common/common/mem.h @@ -0,0 +1,159 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_MEM +#define _H_MEM + +#include +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +SPICE_BEGIN_DECLS + +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +#if !defined alloca +# define alloca __builtin_alloca +#endif +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# ifndef HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +typedef struct SpiceChunk { + uint8_t *data; + uint32_t len; +} SpiceChunk; + +enum { + SPICE_CHUNKS_FLAGS_UNSTABLE = (1<<0), + SPICE_CHUNKS_FLAGS_FREE = (1<<1) +}; + +typedef struct SpiceChunks { + uint32_t data_size; + uint32_t num_chunks; + uint32_t flags; + SpiceChunk chunk[0]; +} SpiceChunks; + +typedef struct SpiceBuffer +{ + size_t capacity; + size_t offset; + uint8_t *buffer; +} SpiceBuffer; + +char *spice_strdup(const char *str) SPICE_GNUC_MALLOC; +char *spice_strndup(const char *str, size_t n_bytes) SPICE_GNUC_MALLOC; +void *spice_memdup(const void *mem, size_t n_bytes) SPICE_GNUC_MALLOC; +void *spice_malloc(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1); +void *spice_malloc0(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1); +void *spice_realloc(void *mem, size_t n_bytes) SPICE_GNUC_WARN_UNUSED_RESULT; +void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2); +void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) SPICE_GNUC_MALLOC; +void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2); +void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_WARN_UNUSED_RESULT; +SpiceChunks *spice_chunks_new(uint32_t count) SPICE_GNUC_MALLOC; +SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) SPICE_GNUC_MALLOC; +void spice_chunks_destroy(SpiceChunks *chunks); +void spice_chunks_linearize(SpiceChunks *chunks); + +size_t spice_strnlen(const char *str, size_t max_len); + +/* Optimize: avoid the call to the (slower) _n function if we can + * determine at compile-time that no overflow happens. + */ +#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) +# define _SPICE_NEW(struct_type, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + size_t __n = (size_t) (n_structs); \ + size_t __s = sizeof (struct_type); \ + void *__p; \ + if (__s == 1) \ + __p = spice_##func (__n); \ + else if (__builtin_constant_p (__n) && \ + __n <= SIZE_MAX / __s) \ + __p = spice_##func (__n * __s); \ + else \ + __p = spice_##func##_n (__n, __s); \ + __p; \ + })) +# define _SPICE_RENEW(struct_type, mem, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + size_t __n = (size_t) (n_structs); \ + size_t __s = sizeof (struct_type); \ + void *__p = (void *) (mem); \ + if (__s == 1) \ + __p = spice_##func (__p, __n); \ + else if (__builtin_constant_p (__n) && \ + __n <= SIZE_MAX / __s) \ + __p = spice_##func (__p, __n * __s); \ + else \ + __p = spice_##func##_n (__p, __n, __s); \ + __p; \ + })) +#else + +/* Unoptimized version: always call the _n() function. */ + +#define _SPICE_NEW(struct_type, n_structs, func) \ + ((struct_type *) spice_##func##_n ((n_structs), sizeof (struct_type))) +#define _SPICE_RENEW(struct_type, mem, n_structs, func) \ + ((struct_type *) spice_##func##_n (mem, (n_structs), sizeof (struct_type))) + +#endif + +#define spice_new(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc) +#define spice_new0(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc0) +#define spice_renew(struct_type, mem, n_structs) _SPICE_RENEW(struct_type, mem, n_structs, realloc) + +/* Buffer management */ +void spice_buffer_reserve(SpiceBuffer *buffer, size_t len); +int spice_buffer_empty(SpiceBuffer *buffer); +uint8_t *spice_buffer_end(SpiceBuffer *buffer); +void spice_buffer_reset(SpiceBuffer *buffer); +void spice_buffer_free(SpiceBuffer *buffer); +void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len); +size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len); +size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/messages.h b/spice-common/common/messages.h new file mode 100644 index 0000000..f537950 --- /dev/null +++ b/spice-common/common/messages.h @@ -0,0 +1,662 @@ +/* + Copyright (C) 2009-2010 Red Hat, Inc. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holder 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 COPYRIGHT HOLDER 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 COPYRIGHT + HOLDER 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 _H_MESSAGES +#define _H_MESSAGES + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef USE_SMARTCARD_012 +#include +#else +#ifdef USE_SMARTCARD +#include +#endif +#endif + +#include "draw.h" + +SPICE_BEGIN_DECLS + +typedef struct SpiceMsgData { + uint32_t data_size; + uint8_t data[0]; +} SpiceMsgData; + +typedef struct SpiceMsgEmpty { + uint8_t padding; +} SpiceMsgEmpty; + +typedef struct SpiceMsgInputsInit { + uint32_t keyboard_modifiers; +} SpiceMsgInputsInit; + +typedef struct SpiceMsgInputsKeyModifiers { + uint32_t modifiers; +} SpiceMsgInputsKeyModifiers; + +typedef struct SpiceMsgMainMultiMediaTime { + uint32_t time; +} SpiceMsgMainMultiMediaTime; + +typedef struct SpiceMigrationDstInfo { + uint16_t port; + uint16_t sport; + uint32_t host_size; + uint8_t *host_data; + uint16_t pub_key_type; + uint32_t pub_key_size; + uint8_t *pub_key_data; + uint32_t cert_subject_size; + uint8_t *cert_subject_data; +} SpiceMigrationDstInfo; + +typedef struct SpiceMsgMainMigrationBegin { + SpiceMigrationDstInfo dst_info; +} SpiceMsgMainMigrationBegin; + +typedef struct SpiceMsgMainMigrateBeginSeamless { + SpiceMigrationDstInfo dst_info; + uint32_t src_mig_version; +} SpiceMsgMainMigrateBeginSeamless; + +typedef struct SpiceMsgcMainMigrateDstDoSeamless { + uint32_t src_version; +} SpiceMsgcMainMigrateDstDoSeamless; + +typedef struct SpiceMsgMainMigrationSwitchHost { + uint16_t port; + uint16_t sport; + uint32_t host_size; + uint8_t *host_data; + uint32_t cert_subject_size; + uint8_t *cert_subject_data; +} SpiceMsgMainMigrationSwitchHost; + + +typedef struct SpiceMsgMigrate { + uint32_t flags; +} SpiceMsgMigrate; + +typedef struct SpiceResourceID { + uint8_t type; + uint64_t id; +} SpiceResourceID; + +typedef struct SpiceResourceList { + uint16_t count; + SpiceResourceID resources[0]; +} SpiceResourceList; + +typedef struct SpiceMsgSetAck { + uint32_t generation; + uint32_t window; +} SpiceMsgSetAck; + +typedef struct SpiceMsgcAckSync { + uint32_t generation; +} SpiceMsgcAckSync; + +typedef struct SpiceWaitForChannel { + uint8_t channel_type; + uint8_t channel_id; + uint64_t message_serial; +} SpiceWaitForChannel; + +typedef struct SpiceMsgWaitForChannels { + uint8_t wait_count; + SpiceWaitForChannel wait_list[0]; +} SpiceMsgWaitForChannels; + +typedef struct SpiceChannelId { + uint8_t type; + uint8_t id; +} SpiceChannelId; + +typedef struct SpiceMsgMainInit { + uint32_t session_id; + uint32_t display_channels_hint; + uint32_t supported_mouse_modes; + uint32_t current_mouse_mode; + uint32_t agent_connected; + uint32_t agent_tokens; + uint32_t multi_media_time; + uint32_t ram_hint; +} SpiceMsgMainInit; + +typedef struct SpiceMsgDisconnect { + uint64_t time_stamp; + uint32_t reason; // SPICE_ERR_? +} SpiceMsgDisconnect; + +typedef struct SpiceMsgNotify { + uint64_t time_stamp; + uint32_t severity; + uint32_t visibilty; + uint32_t what; + uint32_t message_len; + uint8_t message[0]; +} SpiceMsgNotify; + +typedef struct SpiceMsgChannels { + uint32_t num_of_channels; + SpiceChannelId channels[0]; +} SpiceMsgChannels; + +typedef struct SpiceMsgMainName { + uint32_t name_len; + uint8_t name[0]; +} SpiceMsgMainName; + +typedef struct SpiceMsgMainUuid { + uint8_t uuid[16]; +} SpiceMsgMainUuid; + +typedef struct SpiceMsgMainMouseMode { + uint32_t supported_modes; + uint32_t current_mode; +} SpiceMsgMainMouseMode; + +typedef struct SpiceMsgPing { + uint32_t id; + uint64_t timestamp; + void *data; + uint32_t data_len; +} SpiceMsgPing; + +typedef struct SpiceMsgMainAgentDisconnect { + uint32_t error_code; // SPICE_ERR_? +} SpiceMsgMainAgentDisconnect; + +#define SPICE_AGENT_MAX_DATA_SIZE 2048 + +typedef struct SpiceMsgMainAgentTokens { + uint32_t num_tokens; +} SpiceMsgMainAgentTokens, SpiceMsgcMainAgentTokens, SpiceMsgcMainAgentStart; + +typedef struct SpiceMsgMainAgentTokens SpiceMsgMainAgentConnectedTokens; + +typedef struct SpiceMsgcClientInfo { + uint64_t cache_size; +} SpiceMsgcClientInfo; + +typedef struct SpiceMsgcMainMouseModeRequest { + uint32_t mode; +} SpiceMsgcMainMouseModeRequest; + +typedef struct SpiceCursor { + uint32_t flags; + SpiceCursorHeader header; + uint32_t data_size; + uint8_t *data; +} SpiceCursor; + +typedef struct SpiceMsgDisplayMode { + uint32_t x_res; + uint32_t y_res; + uint32_t bits; +} SpiceMsgDisplayMode; + +typedef struct SpiceMsgSurfaceCreate { + uint32_t surface_id; + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t flags; +} SpiceMsgSurfaceCreate; + +typedef struct SpiceMsgSurfaceDestroy { + uint32_t surface_id; +} SpiceMsgSurfaceDestroy; + +typedef struct SpiceMsgDisplayBase { + uint32_t surface_id; + SpiceRect box; + SpiceClip clip; +} SpiceMsgDisplayBase; + +typedef struct SpiceMsgDisplayDrawFill { + SpiceMsgDisplayBase base; + SpiceFill data; +} SpiceMsgDisplayDrawFill; + +typedef struct SpiceMsgDisplayDrawOpaque { + SpiceMsgDisplayBase base; + SpiceOpaque data; +} SpiceMsgDisplayDrawOpaque; + +typedef struct SpiceMsgDisplayDrawCopy { + SpiceMsgDisplayBase base; + SpiceCopy data; +} SpiceMsgDisplayDrawCopy; + +typedef struct SpiceMsgDisplayDrawTransparent { + SpiceMsgDisplayBase base; + SpiceTransparent data; +} SpiceMsgDisplayDrawTransparent; + +typedef struct SpiceMsgDisplayDrawAlphaBlend { + SpiceMsgDisplayBase base; + SpiceAlphaBlend data; +} SpiceMsgDisplayDrawAlphaBlend; + +typedef struct SpiceMsgDisplayDrawComposite { + SpiceMsgDisplayBase base; + SpiceComposite data; +} SpiceMsgDisplayDrawComposite; + +typedef struct SpiceMsgDisplayCopyBits { + SpiceMsgDisplayBase base; + SpicePoint src_pos; +} SpiceMsgDisplayCopyBits; + +typedef SpiceMsgDisplayDrawCopy SpiceMsgDisplayDrawBlend; + +typedef struct SpiceMsgDisplayDrawRop3 { + SpiceMsgDisplayBase base; + SpiceRop3 data; +} SpiceMsgDisplayDrawRop3; + +typedef struct SpiceMsgDisplayDrawBlackness { + SpiceMsgDisplayBase base; + SpiceBlackness data; +} SpiceMsgDisplayDrawBlackness; + +typedef struct SpiceMsgDisplayDrawWhiteness { + SpiceMsgDisplayBase base; + SpiceWhiteness data; +} SpiceMsgDisplayDrawWhiteness; + +typedef struct SpiceMsgDisplayDrawInvers { + SpiceMsgDisplayBase base; + SpiceInvers data; +} SpiceMsgDisplayDrawInvers; + +typedef struct SpiceMsgDisplayDrawStroke { + SpiceMsgDisplayBase base; + SpiceStroke data; +} SpiceMsgDisplayDrawStroke; + +typedef struct SpiceMsgDisplayDrawText { + SpiceMsgDisplayBase base; + SpiceText data; +} SpiceMsgDisplayDrawText; + +typedef struct SpiceMsgDisplayInvalOne { + uint64_t id; +} SpiceMsgDisplayInvalOne; + +typedef struct SpiceMsgDisplayStreamCreate { + uint32_t surface_id; + uint32_t id; + uint32_t flags; + uint32_t codec_type; + uint64_t stamp; + uint32_t stream_width; + uint32_t stream_height; + uint32_t src_width; + uint32_t src_height; + SpiceRect dest; + SpiceClip clip; +} SpiceMsgDisplayStreamCreate; + +typedef struct SpiceStreamDataHeader { + uint32_t id; + uint32_t multi_media_time; +} SpiceStreamDataHeader; + +typedef struct SpiceMsgDisplayStreamData { + SpiceStreamDataHeader base; + uint32_t data_size; + uint8_t data[0]; +} SpiceMsgDisplayStreamData; + +typedef struct SpiceMsgDisplayStreamDataSized { + SpiceStreamDataHeader base; + uint32_t width; + uint32_t height; + SpiceRect dest; + uint32_t data_size; + uint8_t data[0]; +} SpiceMsgDisplayStreamDataSized; + +typedef struct SpiceMsgDisplayStreamClip { + uint32_t id; + SpiceClip clip; +} SpiceMsgDisplayStreamClip; + +typedef struct SpiceMsgDisplayStreamDestroy { + uint32_t id; +} SpiceMsgDisplayStreamDestroy; + +typedef struct SpiceMsgDisplayStreamActivateReport { + uint32_t stream_id; + uint32_t unique_id; + uint32_t max_window_size; + uint32_t timeout_ms; +} SpiceMsgDisplayStreamActivateReport; + +typedef struct SpiceMsgcDisplayStreamReport { + uint32_t stream_id; + uint32_t unique_id; + uint32_t start_frame_mm_time; + uint32_t end_frame_mm_time; + uint32_t num_frames; + uint32_t num_drops; + int32_t last_frame_delay; + uint32_t audio_delay; +} SpiceMsgcDisplayStreamReport; + +typedef struct SpiceMsgcDisplayGlDrawDone { +} SpiceMsgcDisplayGlDrawDone; + +typedef struct SpiceMsgCursorInit { + SpicePoint16 position; + uint16_t trail_length; + uint16_t trail_frequency; + uint8_t visible; + SpiceCursor cursor; +} SpiceMsgCursorInit; + +typedef struct SpiceMsgCursorSet { + SpicePoint16 position; + uint8_t visible; + SpiceCursor cursor; +} SpiceMsgCursorSet; + +typedef struct SpiceMsgCursorMove { + SpicePoint16 position; +} SpiceMsgCursorMove; + +typedef struct SpiceMsgCursorTrail { + uint16_t length; + uint16_t frequency; +} SpiceMsgCursorTrail; + +typedef struct SpiceMsgcDisplayInit { + uint8_t pixmap_cache_id; + int64_t pixmap_cache_size; //in pixels + uint8_t glz_dictionary_id; + int32_t glz_dictionary_window_size; // in pixels +} SpiceMsgcDisplayInit; + +typedef struct SpiceMsgcKeyDown { + uint32_t code; +} SpiceMsgcKeyDown; + +typedef struct SpiceMsgcKeyUp { + uint32_t code; +} SpiceMsgcKeyUp; + +typedef struct SpiceMsgcKeyModifiers { + uint32_t modifiers; +} SpiceMsgcKeyModifiers; + +typedef struct SpiceMsgcMouseMotion { + int32_t dx; + int32_t dy; + uint32_t buttons_state; +} SpiceMsgcMouseMotion; + +typedef struct SpiceMsgcMousePosition { + uint32_t x; + uint32_t y; + uint32_t buttons_state; + uint8_t display_id; +} SpiceMsgcMousePosition; + +typedef struct SpiceMsgcMousePress { + int32_t button; + int32_t buttons_state; +} SpiceMsgcMousePress; + +typedef struct SpiceMsgcMouseRelease { + int32_t button; + int32_t buttons_state; +} SpiceMsgcMouseRelease; + +typedef struct SpiceMsgAudioVolume { + uint8_t nchannels; + uint16_t volume[0]; +} SpiceMsgAudioVolume; + +typedef struct SpiceMsgAudioMute { + uint8_t mute; +} SpiceMsgAudioMute; + +typedef struct SpiceMsgPlaybackMode { + uint32_t time; + uint32_t mode; //SPICE_AUDIO_DATA_MODE_? + uint8_t *data; + uint32_t data_size; +} SpiceMsgPlaybackMode, SpiceMsgcRecordMode; + +typedef struct SpiceMsgPlaybackStart { + uint32_t channels; + uint32_t format; //SPICE_AUDIO_FMT_? + uint32_t frequency; + uint32_t time; +} SpiceMsgPlaybackStart; + +typedef struct SpiceMsgPlaybackPacket { + uint32_t time; + uint8_t *data; + uint32_t data_size; +} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket; + +typedef struct SpiceMsgPlaybackLatency { + uint32_t latency_ms; +} SpiceMsgPlaybackLatency; + +typedef struct SpiceMsgRecordStart { + uint32_t channels; + uint32_t format; //SPICE_AUDIO_FMT_? + uint32_t frequency; +} SpiceMsgRecordStart; + +typedef struct SpiceMsgcRecordStartMark { + uint32_t time; +} SpiceMsgcRecordStartMark; + +typedef struct SpiceMsgTunnelInit { + uint16_t max_num_of_sockets; + uint32_t max_socket_data_size; +} SpiceMsgTunnelInit; + +typedef uint8_t SpiceTunnelIPv4[4]; + +typedef struct SpiceMsgTunnelIpInfo { + uint16_t type; + union { + SpiceTunnelIPv4 ipv4; + } u; + uint8_t data[0]; +} SpiceMsgTunnelIpInfo; + +typedef struct SpiceMsgTunnelServiceIpMap { + uint32_t service_id; + SpiceMsgTunnelIpInfo virtual_ip; +} SpiceMsgTunnelServiceIpMap; + +typedef struct SpiceMsgTunnelSocketOpen { + uint16_t connection_id; + uint32_t service_id; + uint32_t tokens; +} SpiceMsgTunnelSocketOpen; + +/* connection id must be the first field in msgs directed to a specific connection */ + +typedef struct SpiceMsgTunnelSocketFin { + uint16_t connection_id; +} SpiceMsgTunnelSocketFin; + +typedef struct SpiceMsgTunnelSocketClose { + uint16_t connection_id; +} SpiceMsgTunnelSocketClose; + +typedef struct SpiceMsgTunnelSocketData { + uint16_t connection_id; + uint8_t data[0]; +} SpiceMsgTunnelSocketData; + +typedef struct SpiceMsgTunnelSocketTokens { + uint16_t connection_id; + uint32_t num_tokens; +} SpiceMsgTunnelSocketTokens; + +typedef struct SpiceMsgTunnelSocketClosedAck { + uint16_t connection_id; +} SpiceMsgTunnelSocketClosedAck; + +typedef struct SpiceMsgcTunnelAddGenericService { + uint32_t type; + uint32_t id; + uint32_t group; + uint32_t port; + uint64_t name; + uint64_t description; + union { + SpiceMsgTunnelIpInfo ip; + } u; +} SpiceMsgcTunnelAddGenericService; + +typedef struct SpiceMsgcTunnelRemoveService { + uint32_t id; +} SpiceMsgcTunnelRemoveService; + +/* connection id must be the first field in msgs directed to a specific connection */ + +typedef struct SpiceMsgcTunnelSocketOpenAck { + uint16_t connection_id; + uint32_t tokens; +} SpiceMsgcTunnelSocketOpenAck; + +typedef struct SpiceMsgcTunnelSocketOpenNack { + uint16_t connection_id; +} SpiceMsgcTunnelSocketOpenNack; + +typedef struct SpiceMsgcTunnelSocketData { + uint16_t connection_id; + uint8_t data[0]; +} SpiceMsgcTunnelSocketData; + +typedef struct SpiceMsgcTunnelSocketFin { + uint16_t connection_id; +} SpiceMsgcTunnelSocketFin; + +typedef struct SpiceMsgcTunnelSocketClosed { + uint16_t connection_id; +} SpiceMsgcTunnelSocketClosed; + +typedef struct SpiceMsgcTunnelSocketClosedAck { + uint16_t connection_id; +} SpiceMsgcTunnelSocketClosedAck; + +typedef struct SpiceMsgcTunnelSocketTokens { + uint16_t connection_id; + uint32_t num_tokens; +} SpiceMsgcTunnelSocketTokens; + +#ifdef USE_SMARTCARD +typedef struct SpiceMsgSmartcard { + VSCMsgType type; + uint32_t length; + uint32_t reader_id; + uint8_t data[0]; +} SpiceMsgSmartcard; + +typedef struct SpiceMsgcSmartcard { + VSCMsgHeader header; + union { + VSCMsgError error; + VSCMsgATR atr_data; + VSCMsgReaderAdd add; + }; +} SpiceMsgcSmartcard; +#endif + +typedef struct SpiceMsgDisplayHead { + uint32_t id; + uint32_t surface_id; + uint32_t width; + uint32_t height; + uint32_t x; + uint32_t y; + uint32_t flags; +} SpiceHead; + +typedef struct SpiceMsgDisplayMonitorsConfig { + uint16_t count; + uint16_t max_allowed; + SpiceHead heads[0]; +} SpiceMsgDisplayMonitorsConfig; + +typedef struct SpiceMsgPortInit { + uint32_t name_size; + uint8_t *name; + uint8_t opened; +} SpiceMsgPortInit; + +typedef struct SpiceMsgPortEvent { + uint8_t event; +} SpiceMsgPortEvent; + +typedef struct SpiceMsgcPortEvent { + uint8_t event; +} SpiceMsgcPortEvent; + +typedef struct SpiceMsgcDisplayPreferredCompression { + uint8_t image_compression; +} SpiceMsgcDisplayPreferredCompression; + +typedef struct SpiceMsgDisplayGlScanoutUnix { + int drm_dma_buf_fd; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t drm_fourcc_format; + uint32_t flags; +} SpiceMsgDisplayGlScanoutUnix; + +typedef struct SpiceMsgDisplayGlDraw { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +} SpiceMsgDisplayGlDraw; + +SPICE_END_DECLS + +#endif /* _H_SPICE_PROTOCOL */ diff --git a/spice-common/common/pixman_utils.c b/spice-common/common/pixman_utils.c new file mode 100644 index 0000000..81806c9 --- /dev/null +++ b/spice-common/common/pixman_utils.c @@ -0,0 +1,1609 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "spice_common.h" + +#include "pixman_utils.h" + +#include +#include "mem.h" + +/* + * src is used for most OPs, hidden within _equation attribute. For some + * operations (such as "clear" and "noop") src is not used and then we have + * to add SPICE_GNUC_UNUSED, that's just a __attribute__((__unused__)), to + * make GCC happy. + * Also, according to GCC documentation [0], the unused attribute "(...) means + * that the variable is meant to be possibly unused. GCC does not produce a + * warning for this variable.". So, we are safe adding it, even if src is used + * for most OPs. + */ +#define SOLID_RASTER_OP(_name, _size, _type, _equation) \ +static void \ +solid_rop_ ## _name ## _ ## _size (_type *ptr, int len, SPICE_GNUC_UNUSED _type src) \ +{ \ + while (len--) { \ + _type dst = *ptr; \ + if (dst) /* avoid unused warning */{}; \ + *ptr = (_type)(_equation); \ + ptr++; \ + } \ +} \ + +#define TILED_RASTER_OP(_name, _size, _type, _equation) \ +static void \ +tiled_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) \ +{ \ + while (len--) { \ + _type src = *tile; \ + _type dst = *ptr; \ + if (src) /* avoid unused warning */{}; \ + if (dst) /* avoid unused warning */{}; \ + *ptr = (_type)(_equation); \ + ptr++; \ + tile++; \ + if (tile == tile_end) \ + tile -= tile_width; \ + } \ +} \ + +#define COPY_RASTER_OP(_name, _size, _type, _equation) \ +static void \ + copy_rop_ ## _name ## _ ## _size (_type *ptr, _type *src_line, int len) \ +{ \ + while (len--) { \ + _type src = *src_line; \ + _type dst = *ptr; \ + if (src) /* avoid unused warning */ {}; \ + if (dst) /* avoid unused warning */{}; \ + *ptr = (_type)(_equation); \ + ptr++; \ + src_line++; \ + } \ +} \ + +#define RASTER_OP(name, equation) \ + SOLID_RASTER_OP(name, 8, uint8_t, equation) \ + SOLID_RASTER_OP(name, 16, uint16_t, equation) \ + SOLID_RASTER_OP(name, 32, uint32_t, equation) \ + TILED_RASTER_OP(name, 8, uint8_t, equation) \ + TILED_RASTER_OP(name, 16, uint16_t, equation) \ + TILED_RASTER_OP(name, 32, uint32_t, equation) \ + COPY_RASTER_OP(name, 8, uint8_t, equation) \ + COPY_RASTER_OP(name, 16, uint16_t, equation) \ + COPY_RASTER_OP(name, 32, uint32_t, equation) + +RASTER_OP(clear, 0x0) +RASTER_OP(and, src & dst) +RASTER_OP(and_reverse, src & ~dst) +RASTER_OP(copy, src) +RASTER_OP(and_inverted, ~src & dst) +RASTER_OP(noop, dst) +RASTER_OP(xor, src ^ dst) +RASTER_OP(or, src | dst) +RASTER_OP(nor, ~src & ~dst) +RASTER_OP(equiv, ~src ^ dst) +RASTER_OP(invert, ~dst) +RASTER_OP(or_reverse, src | ~dst) +RASTER_OP(copy_inverted, ~src) +RASTER_OP(or_inverted, ~src | dst) +RASTER_OP(nand, ~src | ~dst) +RASTER_OP(set, 0xffffffff) + +typedef void (*solid_rop_8_func_t)(uint8_t *ptr, int len, uint8_t src); +typedef void (*solid_rop_16_func_t)(uint16_t *ptr, int len, uint16_t src); +typedef void (*solid_rop_32_func_t)(uint32_t *ptr, int len, uint32_t src); +typedef void (*tiled_rop_8_func_t)(uint8_t *ptr, int len, + uint8_t *tile, uint8_t *tile_end, int tile_width); +typedef void (*tiled_rop_16_func_t)(uint16_t *ptr, int len, + uint16_t *tile, uint16_t *tile_end, int tile_width); +typedef void (*tiled_rop_32_func_t)(uint32_t *ptr, int len, + uint32_t *tile, uint32_t *tile_end, int tile_width); +typedef void (*copy_rop_8_func_t)(uint8_t *ptr, uint8_t *src, int len); +typedef void (*copy_rop_16_func_t)(uint16_t *ptr, uint16_t *src, int len); +typedef void (*copy_rop_32_func_t)(uint32_t *ptr, uint32_t *src, int len); + +#define ROP_TABLE(_type, _size) \ +static void (*solid_rops_ ## _size[16]) (_type *ptr, int len, _type src) = { \ + solid_rop_clear_ ## _size, \ + solid_rop_and_ ## _size, \ + solid_rop_and_reverse_ ## _size, \ + solid_rop_copy_ ## _size, \ + solid_rop_and_inverted_ ## _size, \ + solid_rop_noop_ ## _size, \ + solid_rop_xor_ ## _size, \ + solid_rop_or_ ## _size, \ + solid_rop_nor_ ## _size, \ + solid_rop_equiv_ ## _size, \ + solid_rop_invert_ ## _size, \ + solid_rop_or_reverse_ ## _size, \ + solid_rop_copy_inverted_ ## _size, \ + solid_rop_or_inverted_ ## _size, \ + solid_rop_nand_ ## _size, \ + solid_rop_set_ ## _size \ +}; \ +static void (*tiled_rops_ ## _size[16]) (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) = { \ + tiled_rop_clear_ ## _size, \ + tiled_rop_and_ ## _size, \ + tiled_rop_and_reverse_ ## _size, \ + tiled_rop_copy_ ## _size, \ + tiled_rop_and_inverted_ ## _size, \ + tiled_rop_noop_ ## _size, \ + tiled_rop_xor_ ## _size, \ + tiled_rop_or_ ## _size, \ + tiled_rop_nor_ ## _size, \ + tiled_rop_equiv_ ## _size, \ + tiled_rop_invert_ ## _size, \ + tiled_rop_or_reverse_ ## _size, \ + tiled_rop_copy_inverted_ ## _size, \ + tiled_rop_or_inverted_ ## _size, \ + tiled_rop_nand_ ## _size, \ + tiled_rop_set_ ## _size \ +}; \ +static void (*copy_rops_ ## _size[16]) (_type *ptr, _type *tile, int len) = { \ + copy_rop_clear_ ## _size, \ + copy_rop_and_ ## _size, \ + copy_rop_and_reverse_ ## _size, \ + copy_rop_copy_ ## _size, \ + copy_rop_and_inverted_ ## _size, \ + copy_rop_noop_ ## _size, \ + copy_rop_xor_ ## _size, \ + copy_rop_or_ ## _size, \ + copy_rop_nor_ ## _size, \ + copy_rop_equiv_ ## _size, \ + copy_rop_invert_ ## _size, \ + copy_rop_or_reverse_ ## _size, \ + copy_rop_copy_inverted_ ## _size, \ + copy_rop_or_inverted_ ## _size, \ + copy_rop_nand_ ## _size, \ + copy_rop_set_ ## _size \ +}; + +ROP_TABLE(uint8_t, 8) +ROP_TABLE(uint16_t, 16) +ROP_TABLE(uint32_t, 32) + +/* We can't get the real bits per pixel info from pixman_image_t, + only the DEPTH which is the sum of all a+r+g+b bits, which + is e.g. 24 for 32bit xRGB. We really want the bpp, so + we have this ugly conversion thing */ +int spice_pixman_image_get_bpp(pixman_image_t *image) +{ + int depth; + + depth = pixman_image_get_depth(image); + if (depth == 24) { + return 32; + } + if (depth == 15) { + return 16; + } + return depth; +} + +void spice_pixman_fill_rect(pixman_image_t *dest, + int x, int y, + int width, int height, + uint32_t value) +{ + uint32_t *bits; + int stride, depth; + uint32_t byte_width; + uint8_t *byte_line; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + spice_assert(x >= 0); + spice_assert(y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(x + width <= pixman_image_get_width(dest)); + spice_assert(y + height <= pixman_image_get_height(dest)); + + if (pixman_fill(bits, + stride / 4, + depth, + x, y, + width, height, + value)) { + return; + } + + if (depth == 8) { + byte_line = ((uint8_t *)bits) + stride * y + x; + byte_width = width; + value = (value & 0xff) * 0x01010101; + } else if (depth == 16) { + byte_line = ((uint8_t *)bits) + stride * y + x * 2; + byte_width = 2 * width; + value = (value & 0xffff) * 0x00010001; + } else { + spice_assert (depth == 32); + byte_line = ((uint8_t *)bits) + stride * y + x * 4; + byte_width = 4 * width; + } + + while (height--) { + int w; + uint8_t *d = byte_line; + + byte_line += stride; + w = byte_width; + + while (w >= 1 && ((uintptr_t)d & 1)) { + *(uint8_t *)d = (value & 0xff); + w--; + d++; + } + + while (w >= 2 && ((uintptr_t)d & 3)) { + *(uint16_t *)d = value; + w -= 2; + d += 2; + } + + while (w >= 4 && ((uintptr_t)d & 7)) { + *(uint32_t *)d = value; + + w -= 4; + d += 4; + } + + while (w >= 4) { + *(uint32_t *)d = value; + + w -= 4; + d += 4; + } + + while (w >= 2) { + *(uint16_t *)d = value; + w -= 2; + d += 2; + } + + while (w >= 1) { + *(uint8_t *)d = (value & 0xff); + w--; + d++; + } + } +} + +void spice_pixman_fill_rect_rop(pixman_image_t *dest, + int x, int y, + int width, int height, + uint32_t value, + SpiceROP rop) +{ + uint32_t *bits; + int stride, depth; + uint8_t *byte_line; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + spice_assert(x >= 0); + spice_assert(y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(x + width <= pixman_image_get_width(dest)); + spice_assert(y + height <= pixman_image_get_height(dest)); + spice_assert(rop < 16); + + if (depth == 8) { + solid_rop_8_func_t rop_func = solid_rops_8[rop]; + + byte_line = ((uint8_t *)bits) + stride * y + x; + while (height--) { + rop_func((uint8_t *)byte_line, width, (uint8_t)value); + byte_line += stride; + } + + } else if (depth == 16) { + solid_rop_16_func_t rop_func = solid_rops_16[rop]; + + byte_line = ((uint8_t *)bits) + stride * y + x * 2; + while (height--) { + rop_func((uint16_t *)byte_line, width, (uint16_t)value); + byte_line += stride; + } + } else { + solid_rop_32_func_t rop_func = solid_rops_32[rop]; + + byte_line = ((uint8_t *)bits) + stride * y + x * 4; + while (height--) { + rop_func((uint32_t *)byte_line, width, (uint32_t)value); + byte_line += stride; + } + } +} + +void spice_pixman_tile_rect(pixman_image_t *dest, + int x, int y, + int width, int height, + pixman_image_t *tile, + int offset_x, + int offset_y) +{ + uint32_t *bits, *tile_bits; + int stride, depth; + int tile_width, tile_height, tile_stride; + uint8_t *byte_line; + uint8_t *tile_line; + int tile_start_x, tile_start_y, tile_end_dx; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + tile_bits = pixman_image_get_data(tile); + tile_stride = pixman_image_get_stride(tile); + tile_width = pixman_image_get_width(tile); + tile_height = pixman_image_get_height(tile); + + spice_assert(x >= 0); + spice_assert(y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(x + width <= pixman_image_get_width(dest)); + spice_assert(y + height <= pixman_image_get_height(dest)); + spice_assert(depth == spice_pixman_image_get_bpp(tile)); + + tile_start_x = (x - offset_x) % tile_width; + if (tile_start_x < 0) { + tile_start_x += tile_width; + } + tile_start_y = (y - offset_y) % tile_height; + if (tile_start_y < 0) { + tile_start_y += tile_height; + } + tile_end_dx = tile_width - tile_start_x; + + if (depth == 8) { + byte_line = ((uint8_t *)bits) + stride * y + x; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x; + while (height--) { + tiled_rop_copy_8((uint8_t *)byte_line, width, + (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + + } else if (depth == 16) { + byte_line = ((uint8_t *)bits) + stride * y + x * 2; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2; + while (height--) { + tiled_rop_copy_16((uint16_t *)byte_line, width, + (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + } else { + spice_assert (depth == 32); + + byte_line = ((uint8_t *)bits) + stride * y + x * 4; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4; + while (height--) { + tiled_rop_copy_32((uint32_t *)byte_line, width, + (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + } +} + +void spice_pixman_tile_rect_rop(pixman_image_t *dest, + int x, int y, + int width, int height, + pixman_image_t *tile, + int offset_x, + int offset_y, + SpiceROP rop) +{ + uint32_t *bits, *tile_bits; + int stride, depth; + int tile_width, tile_height, tile_stride; + uint8_t *byte_line; + uint8_t *tile_line; + int tile_start_x, tile_start_y, tile_end_dx; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + tile_bits = pixman_image_get_data(tile); + tile_stride = pixman_image_get_stride(tile); + tile_width = pixman_image_get_width(tile); + tile_height = pixman_image_get_height(tile); + + spice_assert(x >= 0); + spice_assert(y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(x + width <= pixman_image_get_width(dest)); + spice_assert(y + height <= pixman_image_get_height(dest)); + spice_assert(rop < 16); + spice_assert(depth == spice_pixman_image_get_bpp(tile)); + + tile_start_x = (x - offset_x) % tile_width; + if (tile_start_x < 0) { + tile_start_x += tile_width; + } + tile_start_y = (y - offset_y) % tile_height; + if (tile_start_y < 0) { + tile_start_y += tile_height; + } + tile_end_dx = tile_width - tile_start_x; + + if (depth == 8) { + tiled_rop_8_func_t rop_func = tiled_rops_8[rop]; + + byte_line = ((uint8_t *)bits) + stride * y + x; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x; + while (height--) { + rop_func((uint8_t *)byte_line, width, + (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + + } else if (depth == 16) { + tiled_rop_16_func_t rop_func = tiled_rops_16[rop]; + + byte_line = ((uint8_t *)bits) + stride * y + x * 2; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2; + while (height--) { + rop_func((uint16_t *)byte_line, width, + (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + } else { + tiled_rop_32_func_t rop_func = tiled_rops_32[rop]; + + spice_assert (depth == 32); + + byte_line = ((uint8_t *)bits) + stride * y + x * 4; + tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4; + while (height--) { + rop_func((uint32_t *)byte_line, width, + (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, + tile_width); + byte_line += stride; + tile_line += tile_stride; + if (++tile_start_y == tile_height) { + tile_line -= tile_height * tile_stride; + tile_start_y = 0; + } + } + } +} + + +void spice_pixman_blit(pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height) +{ + uint32_t *bits, *src_bits; + int stride, depth, src_depth; + int src_width, src_height, src_stride; + uint8_t *byte_line; + uint8_t *src_line; + int byte_width; + + if (!src) { + fprintf(stderr, "missing src!"); + return; + } + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + src_bits = pixman_image_get_data(src); + src_stride = pixman_image_get_stride(src); + src_width = pixman_image_get_width(src); + src_height = pixman_image_get_height(src); + src_depth = spice_pixman_image_get_bpp(src); + + /* Clip source */ + if (src_x < 0) { + width += src_x; + dest_x -= src_x; + src_x = 0; + } + if (src_y < 0) { + height += src_y; + dest_y -= src_y; + src_y = 0; + } + if (src_x + width > src_width) { + width = src_width - src_x; + } + if (src_y + height > src_height) { + height = src_height - src_y; + } + + if (width <= 0 || height <= 0) { + return; + } + + spice_assert(src_x >= 0); + spice_assert(src_y >= 0); + spice_assert(dest_x >= 0); + spice_assert(dest_y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(dest_x + width <= pixman_image_get_width(dest)); + spice_assert(dest_y + height <= pixman_image_get_height(dest)); + spice_assert(src_x + width <= pixman_image_get_width(src)); + spice_assert(src_y + height <= pixman_image_get_height(src)); + spice_assert(depth == src_depth); + + if (pixman_blt(src_bits, + bits, + src_stride / 4, + stride / 4, + depth, depth, + src_x, src_y, + dest_x, dest_y, + width, height)) { + return; + } + + if (depth == 8) { + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; + byte_width = width; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; + } else if (depth == 16) { + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; + byte_width = width * 2; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; + } else { + spice_assert (depth == 32); + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; + byte_width = width * 4; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; + } + + while (height--) { + memcpy(byte_line, src_line, byte_width); + byte_line += stride; + src_line += src_stride; + } +} + +void spice_pixman_blit_rop (pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + SpiceROP rop) +{ + uint32_t *bits, *src_bits; + int stride, depth, src_depth; + int src_width, src_height, src_stride; + uint8_t *byte_line; + uint8_t *src_line; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + src_bits = pixman_image_get_data(src); + src_stride = pixman_image_get_stride(src); + src_width = pixman_image_get_width(src); + src_height = pixman_image_get_height(src); + src_depth = spice_pixman_image_get_bpp(src); + + /* Clip source */ + if (src_x < 0) { + width += src_x; + dest_x -= src_x; + src_x = 0; + } + if (src_y < 0) { + height += src_y; + dest_y -= src_y; + src_y = 0; + } + if (src_x + width > src_width) { + width = src_width - src_x; + } + if (src_y + height > src_height) { + height = src_height - src_y; + } + + if (width <= 0 || height <= 0) { + return; + } + + spice_assert(src_x >= 0); + spice_assert(src_y >= 0); + spice_assert(dest_x >= 0); + spice_assert(dest_y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(dest_x + width <= pixman_image_get_width(dest)); + spice_assert(dest_y + height <= pixman_image_get_height(dest)); + spice_assert(src_x + width <= pixman_image_get_width(src)); + spice_assert(src_y + height <= pixman_image_get_height(src)); + spice_assert(depth == src_depth); + + if (depth == 8) { + copy_rop_8_func_t rop_func = copy_rops_8[rop]; + + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; + + while (height--) { + rop_func((uint8_t *)byte_line, (uint8_t *)src_line, width); + byte_line += stride; + src_line += src_stride; + } + } else if (depth == 16) { + copy_rop_16_func_t rop_func = copy_rops_16[rop]; + + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; + + while (height--) { + rop_func((uint16_t *)byte_line, (uint16_t *)src_line, width); + byte_line += stride; + src_line += src_stride; + } + } else { + copy_rop_32_func_t rop_func = copy_rops_32[rop]; + + spice_assert (depth == 32); + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; + + while (height--) { + rop_func((uint32_t *)byte_line, (uint32_t *)src_line, width); + byte_line += stride; + src_line += src_stride; + } + } + +} + +void spice_pixman_blit_colorkey (pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + uint32_t transparent_color) +{ + uint32_t *bits, *src_bits; + int stride, depth; + int src_width, src_height, src_stride; + uint8_t *byte_line; + uint8_t *src_line; + int x; + + bits = pixman_image_get_data(dest); + stride = pixman_image_get_stride(dest); + depth = spice_pixman_image_get_bpp(dest); + /* stride is in bytes, depth in bits */ + + src_bits = pixman_image_get_data(src); + src_stride = pixman_image_get_stride(src); + src_width = pixman_image_get_width(src); + src_height = pixman_image_get_height(src); + + /* Clip source */ + if (src_x < 0) { + width += src_x; + dest_x -= src_x; + src_x = 0; + } + if (src_y < 0) { + height += src_y; + dest_y -= src_y; + src_y = 0; + } + if (src_x + width > src_width) { + width = src_width - src_x; + } + if (src_y + height > src_height) { + height = src_height - src_y; + } + + if (width <= 0 || height <= 0) { + return; + } + + spice_assert(src_x >= 0); + spice_assert(src_y >= 0); + spice_assert(dest_x >= 0); + spice_assert(dest_y >= 0); + spice_assert(width > 0); + spice_assert(height > 0); + spice_assert(dest_x + width <= pixman_image_get_width(dest)); + spice_assert(dest_y + height <= pixman_image_get_height(dest)); + spice_assert(src_x + width <= pixman_image_get_width(src)); + spice_assert(src_y + height <= pixman_image_get_height(src)); + spice_assert(depth == spice_pixman_image_get_bpp(src)); + + if (depth == 8) { + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; + + while (height--) { + uint8_t *d = (uint8_t *)byte_line; + uint8_t *s = (uint8_t *)src_line; + for (x = 0; x < width; x++) { + uint8_t val = *s; + if (val != (uint8_t)transparent_color) { + *d = val; + } + s++; d++; + } + + byte_line += stride; + src_line += src_stride; + } + } else if (depth == 16) { + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; + + while (height--) { + uint16_t *d = (uint16_t *)byte_line; + uint16_t *s = (uint16_t *)src_line; + + for (x = 0; x < width; x++) { + uint16_t val = *s; + if (val != (uint16_t)transparent_color) { + *d = val; + } + s++; d++; + } + + byte_line += stride; + src_line += src_stride; + } + } else { + spice_assert (depth == 32); + byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; + src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; + + while (height--) { + uint32_t *d = (uint32_t *)byte_line; + uint32_t *s = (uint32_t *)src_line; + + transparent_color &= 0xffffff; + for (x = 0; x < width; x++) { + uint32_t val = *s; + if ((0xffffff & val) != transparent_color) { + *d = val; + } + s++; d++; + } + + byte_line += stride; + src_line += src_stride; + } + } +} + +static void copy_bits_up(uint8_t *data, const int stride, int bpp, + const int src_x, const int src_y, + const int width, const int height, + const int dest_x, const int dest_y) +{ + uint8_t *src = data + src_y * stride + src_x * bpp; + uint8_t *dest = data + dest_y * stride + dest_x * bpp; + uint8_t *end = dest + height * stride; + for (; dest != end; dest += stride, src += stride) { + memcpy(dest, src, width * bpp); + } +} + +static void copy_bits_down(uint8_t *data, const int stride, int bpp, + const int src_x, const int src_y, + const int width, const int height, + const int dest_x, const int dest_y) +{ + uint8_t *src = data + (src_y + height - 1) * stride + src_x * bpp; + uint8_t *end = data + (dest_y - 1) * stride + dest_x * bpp; + uint8_t *dest = end + height * stride; + + for (; dest != end; dest -= stride, src -= stride) { + memcpy(dest, src, width * bpp); + } +} + +static void copy_bits_same_line(uint8_t *data, const int stride, int bpp, + const int src_x, const int src_y, + const int width, const int height, + const int dest_x, const int dest_y) +{ + uint8_t *src = data + src_y * stride + src_x * bpp; + uint8_t *dest = data + dest_y * stride + dest_x * bpp; + uint8_t *end = dest + height * stride; + for (; dest != end; dest += stride, src += stride) { + memmove(dest, src, width * bpp); + } +} + +void spice_pixman_copy_rect (pixman_image_t *image, + int src_x, int src_y, + int width, int height, + int dest_x, int dest_y) +{ + uint8_t *data; + int stride; + int bpp; + + data = (uint8_t *)pixman_image_get_data(image); + stride = pixman_image_get_stride(image); + bpp = spice_pixman_image_get_bpp(image) / 8; + + if (dest_y > src_y) { + copy_bits_down(data, stride, bpp, + src_x, src_y, + width, height, + dest_x, dest_y); + } else if (dest_y < src_y) { + copy_bits_up(data, stride, bpp, + src_x, src_y, + width, height, + dest_x, dest_y); + } else { + copy_bits_same_line(data, stride, bpp, + src_x, src_y, + width, height, + dest_x, dest_y); + } +} + +pixman_bool_t spice_pixman_region32_init_rects (pixman_region32_t *region, + const SpiceRect *rects, + int count) +{ + /* These types are compatible, so just cast */ + return pixman_region32_init_rects(region, (pixman_box32_t *)rects, count); +} + +pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format) +{ + switch (surface_format) { + case SPICE_SURFACE_FMT_1_A: + return PIXMAN_a1; + case SPICE_SURFACE_FMT_8_A: + return PIXMAN_a8; + case SPICE_SURFACE_FMT_16_555: + return PIXMAN_x1r5g5b5; + case SPICE_SURFACE_FMT_16_565: + return PIXMAN_r5g6b5; + case SPICE_SURFACE_FMT_32_xRGB: + return PIXMAN_x8r8g8b8; + case SPICE_SURFACE_FMT_32_ARGB: + return PIXMAN_a8r8g8b8; + default: + printf("Unknown surface format %d\n", surface_format); + spice_abort(); + break; + } + return (pixman_format_code_t)0; /* Not reached */ +} + +/* Returns the "spice native" pixman version of a specific bitmap format. + * This isn't bitwise the same as the bitmap format, for instance we + * typically convert indexed to real color modes and use the standard + * surface modes rather than weird things like 24bit + */ +pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format, + uint32_t palette_surface_format) +{ + switch (bitmap_format) { + case SPICE_BITMAP_FMT_1BIT_LE: + case SPICE_BITMAP_FMT_1BIT_BE: + case SPICE_BITMAP_FMT_4BIT_LE: + case SPICE_BITMAP_FMT_4BIT_BE: + case SPICE_BITMAP_FMT_8BIT: + /* Indexed mode palettes are the same as their destination canvas format */ + return spice_surface_format_to_pixman(palette_surface_format); + + case SPICE_BITMAP_FMT_16BIT: + return PIXMAN_x1r5g5b5; + + case SPICE_BITMAP_FMT_24BIT: + case SPICE_BITMAP_FMT_32BIT: + return PIXMAN_x8r8g8b8; + + case SPICE_BITMAP_FMT_RGBA: + return PIXMAN_a8r8g8b8; + + case SPICE_BITMAP_FMT_8BIT_A: + return PIXMAN_a8; + + case SPICE_BITMAP_FMT_INVALID: + default: + printf("Unknown bitmap format %d\n", bitmap_format); + spice_abort(); + return PIXMAN_a8r8g8b8; + } +} + +/* Tries to view a spice bitmap as a pixman_image_t without copying, + * will often fail due to unhandled formats or strides. + */ +pixman_image_t *spice_bitmap_try_as_pixman(int src_format, + int flags, + int width, + int height, + uint8_t *data, + int stride) +{ + pixman_format_code_t pixman_format; + + /* Pixman stride must be multiple of 4 */ + if (stride % 4 != 0) { + return NULL; + } + + switch (src_format) { + case SPICE_BITMAP_FMT_32BIT: + pixman_format = PIXMAN_LE_x8r8g8b8; + break; + case SPICE_BITMAP_FMT_RGBA: + pixman_format = PIXMAN_LE_a8r8g8b8; + break; + case SPICE_BITMAP_FMT_24BIT: + pixman_format = PIXMAN_LE_r8g8b8; + break; + case SPICE_BITMAP_FMT_16BIT: +#ifdef WORDS_BIGENDIAN + return NULL; +#else + pixman_format = PIXMAN_x1r5g5b5; +#endif + break; + + default: + return NULL; + } + + if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + data += stride * (height - 1); + stride = -stride; + } + + return pixman_image_create_bits (pixman_format, + width, + height, + (uint32_t *)data, + stride); +} + +#ifdef WORDS_BIGENDIAN +#define UINT16_FROM_LE(x) SPICE_BYTESWAP16(x) +#define UINT32_FROM_LE(x) SPICE_BYTESWAP32(x) +#else +#define UINT16_FROM_LE(x) (x) +#define UINT32_FROM_LE(x) (x) +#endif + +static inline uint32_t rgb_16_555_to_32(uint16_t color) +{ + uint32_t ret; + + ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2); + ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1); + ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4); + + return ret; +} + +static inline uint16_t rgb_32_to_16_555(uint32_t color) +{ + return + (((color) >> 3) & 0x001f) | + (((color) >> 6) & 0x03e0) | + (((color) >> 9) & 0x7c00); +} + + +static void bitmap_32_to_32(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ +#ifdef WORDS_BIGENDIAN + for (; src != end; src += src_stride, dest += dest_stride) { + uint32_t* src_line = (uint32_t *)src; + uint32_t* src_line_end = src_line + width; + uint32_t* dest_line = (uint32_t *)dest; + + for (; src_line < src_line_end; ++dest_line, ++src_line) { + *dest_line = UINT32_FROM_LE(*src_line); + } + } +#else + for (; src != end; src += src_stride, dest += dest_stride) { + memcpy(dest, src, width * 4); + } +#endif +} + +static void bitmap_8_to_8(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ + for (; src != end; src += src_stride, dest += dest_stride) { + memcpy(dest, src, width); + } +} + +static void bitmap_24_to_32(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ + for (; src != end; src += src_stride, dest += dest_stride) { + uint8_t* src_line = src; + uint8_t* src_line_end = src_line + width * 3; + uint32_t* dest_line = (uint32_t *)dest; + + for (; src_line < src_line_end; ++dest_line) { + uint32_t r, g, b; + b = *(src_line++); + g = *(src_line++); + r = *(src_line++); + *dest_line = (r << 16) | (g << 8) | (b); + } + } +} + +static void bitmap_16_to_16_555(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ +#ifdef WORDS_BIGENDIAN + for (; src != end; src += src_stride, dest += dest_stride) { + uint16_t* src_line = (uint16_t *)src; + uint16_t* src_line_end = src_line + width; + uint16_t* dest_line = (uint16_t *)dest; + + for (; src_line < src_line_end; ++dest_line, ++src_line) { + *dest_line = UINT16_FROM_LE(*src_line); + } + } +#else + for (; src != end; src += src_stride, dest += dest_stride) { + memcpy(dest, src, width * 2); + } +#endif +} + +static void bitmap_8_32_to_32(uint8_t *dest, int dest_stride, + uint8_t *src, int src_stride, + int width, uint8_t *end, + SpicePalette *palette) +{ + uint32_t local_ents[256]; + uint32_t *ents; + int n_ents; +#ifdef WORDS_BIGENDIAN + int i; +#endif + + if (!palette) { + spice_error("No palette"); + return; + } + + n_ents = MIN(palette->num_ents, 256); + ents = palette->ents; + + if (n_ents < 255 +#ifdef WORDS_BIGENDIAN + || TRUE +#endif + ) { + memcpy(local_ents, ents, n_ents*4); + ents = local_ents; + +#ifdef WORDS_BIGENDIAN + for (i = 0; i < n_ents; i++) { + ents[i] = UINT32_FROM_LE(ents[i]); + } +#endif + } + + for (; src != end; src += src_stride, dest += dest_stride) { + uint32_t *dest_line = (uint32_t*)dest; + uint8_t *src_line = src; + uint8_t *src_line_end = src_line + width; + + while (src_line < src_line_end) { + *(dest_line++) = ents[*(src_line++)]; + } + } +} + +static void bitmap_8_16_to_16_555(uint8_t *dest, int dest_stride, + uint8_t *src, int src_stride, + int width, uint8_t *end, + SpicePalette *palette) +{ + uint32_t local_ents[256]; + uint32_t *ents; + int n_ents; +#ifdef WORDS_BIGENDIAN + int i; +#endif + + if (!palette) { + spice_error("No palette"); + return; + } + + n_ents = MIN(palette->num_ents, 256); + ents = palette->ents; + + if (n_ents < 255 +#ifdef WORDS_BIGENDIAN + || TRUE +#endif + ) { + memcpy(local_ents, ents, n_ents*4); + ents = local_ents; + +#ifdef WORDS_BIGENDIAN + for (i = 0; i < n_ents; i++) { + ents[i] = UINT32_FROM_LE(ents[i]); + } +#endif + } + + for (; src != end; src += src_stride, dest += dest_stride) { + uint16_t *dest_line = (uint16_t*)dest; + uint8_t *src_line = src; + uint8_t *src_line_end = src_line + width; + + while (src_line < src_line_end) { + *(dest_line++) = ents[*(src_line++)]; + } + } +} + +static void bitmap_4be_32_to_32(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end, + SpicePalette *palette) +{ + uint32_t local_ents[16]; + uint32_t *ents; + int n_ents; +#ifdef WORDS_BIGENDIAN + int i; +#endif + + if (!palette) { + spice_error("No palette"); + return; + } + + n_ents = MIN(palette->num_ents, 16); + ents = palette->ents; + + if (n_ents < 16 +#ifdef WORDS_BIGENDIAN + || TRUE +#endif + ) { + memcpy(local_ents, ents, n_ents*4); + ents = local_ents; + +#ifdef WORDS_BIGENDIAN + for (i = 0; i < n_ents; i++) { + ents[i] = UINT32_FROM_LE(ents[i]); + } +#endif + } + + for (; src != end; src += src_stride, dest += dest_stride) { + uint32_t *dest_line = (uint32_t *)dest; + uint8_t *row = src; + int i; + + for (i = 0; i < (width >> 1); i++) { + *(dest_line++) = ents[(*row >> 4) & 0x0f]; + *(dest_line++) = ents[*(row++) & 0x0f]; + } + if (width & 1) { + *(dest_line) = ents[(*row >> 4) & 0x0f]; + } + } +} + +static void bitmap_4be_16_to_16_555(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end, + SpicePalette *palette) +{ + uint32_t local_ents[16]; + uint32_t *ents; + int n_ents; +#ifdef WORDS_BIGENDIAN + int i; +#endif + + if (!palette) { + spice_error("No palette"); + return; + } + + n_ents = MIN(palette->num_ents, 16); + ents = palette->ents; + + if (n_ents < 16 +#ifdef WORDS_BIGENDIAN + || TRUE +#endif + ) { + memcpy(local_ents, ents, n_ents*4); + ents = local_ents; + +#ifdef WORDS_BIGENDIAN + for (i = 0; i < n_ents; i++) { + ents[i] = UINT32_FROM_LE(ents[i]); + } +#endif + } + + for (; src != end; src += src_stride, dest += dest_stride) { + uint16_t *dest_line = (uint16_t *)dest; + uint8_t *row = src; + int i; + + for (i = 0; i < (width >> 1); i++) { + *(dest_line++) = ents[(*row >> 4) & 0x0f]; + *(dest_line++) = ents[*(row++) & 0x0f]; + } + if (width & 1) { + *(dest_line) = ents[(*row >> 4) & 0x0f]; + } + } +} + +static inline int test_bit_be(void* addr, int bit) +{ + return !!(((uint8_t*)addr)[bit >> 3] & (0x80 >> (bit & 0x07))); +} + +static void bitmap_1be_32_to_32(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end, + SpicePalette *palette) +{ + uint32_t fore_color; + uint32_t back_color; + + spice_assert(palette != NULL); + + if (!palette) { + return; + } + + fore_color = UINT32_FROM_LE(palette->ents[1]); + back_color = UINT32_FROM_LE(palette->ents[0]); + + for (; src != end; src += src_stride, dest += dest_stride) { + uint32_t* dest_line = (uint32_t*)dest; + int i; + + for (i = 0; i < width; i++) { + if (test_bit_be(src, i)) { + *(dest_line++) = fore_color; + } else { + *(dest_line++) = back_color; + } + } + } +} + + +static void bitmap_1be_16_to_16_555(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end, + SpicePalette *palette) +{ + uint16_t fore_color; + uint16_t back_color; + + spice_assert(palette != NULL); + + if (!palette) { + return; + } + + fore_color = (uint16_t) UINT32_FROM_LE(palette->ents[1]); + back_color = (uint16_t) UINT32_FROM_LE(palette->ents[0]); + + for (; src != end; src += src_stride, dest += dest_stride) { + uint16_t* dest_line = (uint16_t*)dest; + int i; + + for (i = 0; i < width; i++) { + if (test_bit_be(src, i)) { + *(dest_line++) = fore_color; + } else { + *(dest_line++) = back_color; + } + } + } +} + +#ifdef NOT_USED_ATM + +static void bitmap_16_to_32(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ + for (; src != end; src += src_stride, dest += dest_stride) { + uint16_t* src_line = (uint16_t*)src; + uint16_t* src_line_end = src_line + width; + uint32_t* dest_line = (uint32_t*)dest; + + for (; src_line < src_line_end; ++dest_line, src_line++) { + *dest_line = rgb_16_555_to_32(UINT16_FROM_LE(*src_line)); + } + } +} + +static void bitmap_32_to_16_555(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ + for (; src != end; src += src_stride, dest += dest_stride) { + uint32_t* src_line = (uint32_t *)src; + uint32_t* src_line_end = src_line + width; + uint16_t* dest_line = (uint16_t *)dest; + + for (; src_line < src_line_end; ++dest_line, ++src_line) { + *dest_line = rgb_32_to_16_555(UINT16_FROM_LE(*src_line)); + } + } +} + + +static void bitmap_24_to_16_555(uint8_t* dest, int dest_stride, + uint8_t* src, int src_stride, + int width, uint8_t* end) +{ + for (; src != end; src += src_stride, dest += dest_stride) { + uint8_t* src_line = src; + uint8_t* src_line_end = src_line + width * 3; + uint16_t* dest_line = (uint16_t *)dest; + + for (; src_line < src_line_end; ++dest_line) { + uint8_t r, g, b; + b = *(src_line++); + g = *(src_line++); + r = *(src_line++); + *dest_line = rgb_32_to_16_555(r << 24 | g << 16 | b); + } + } +} + +#endif + +/* This assumes that the dest, if set is the same format as + spice_bitmap_format_to_pixman would have picked */ +pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image, + int src_format, + int flags, + int width, + int height, + uint8_t *src, + int src_stride, + uint32_t palette_surface_format, + SpicePalette *palette) +{ + uint8_t* dest; + int dest_stride; + uint8_t* end; + + if (dest_image == NULL) { + pixman_format_code_t dest_format; + + dest_format = spice_bitmap_format_to_pixman(src_format, + palette_surface_format); + dest_image = pixman_image_create_bits (dest_format, + width, height, + NULL, 0); + } + + dest = (uint8_t *)pixman_image_get_data(dest_image); + dest_stride = pixman_image_get_stride(dest_image); + if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { + spice_assert(height > 0); + dest += dest_stride * (height - 1); + dest_stride = -dest_stride; + } + end = src + (height * src_stride); + + switch (src_format) { + case SPICE_BITMAP_FMT_32BIT: + case SPICE_BITMAP_FMT_RGBA: + bitmap_32_to_32(dest, dest_stride, src, src_stride, width, end); + break; + case SPICE_BITMAP_FMT_8BIT_A: + bitmap_8_to_8(dest, dest_stride, src, src_stride, width, end); + break; + case SPICE_BITMAP_FMT_24BIT: + bitmap_24_to_32(dest, dest_stride, src, src_stride, width, end); + break; + case SPICE_BITMAP_FMT_16BIT: + bitmap_16_to_16_555(dest, dest_stride, src, src_stride, width, end); + break; + case SPICE_BITMAP_FMT_8BIT: + if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || + palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { + bitmap_8_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); + } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { + bitmap_8_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); + } else { + spice_error("Unsupported palette format"); + } + break; + case SPICE_BITMAP_FMT_4BIT_BE: + if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || + palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { + bitmap_4be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); + } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { + bitmap_4be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); + } else { + spice_error("Unsupported palette format"); + } + break; + case SPICE_BITMAP_FMT_1BIT_BE: + if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || + palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { + bitmap_1be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); + } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { + bitmap_1be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); + } else { + spice_error("Unsupported palette format"); + } + break; + default: + spice_error("Unsupported bitmap format"); + break; + } + + return dest_image; +} + +static int pixman_format_compatible (pixman_format_code_t dest_format, + pixman_format_code_t src_format) +{ + if (dest_format == src_format) { + return TRUE; + } + + if (src_format == PIXMAN_a8r8g8b8 && + dest_format == PIXMAN_x8r8g8b8) { + /* This is the same, we just ignore the alphas */ + return TRUE; + } + + return FALSE; +} + +pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format, + pixman_image_t *dest_image, + int src_format, + int flags, + int width, + int height, + uint8_t *src, + int src_stride, + uint32_t palette_surface_format, + SpicePalette *palette) +{ + pixman_image_t *src_image; + pixman_format_code_t native_format; + + if (dest_image == NULL) { + dest_image = pixman_image_create_bits (dest_format, + width, height, + NULL, 0); + } + + native_format = + spice_bitmap_format_to_pixman(src_format, palette_surface_format); + + if (pixman_format_compatible (dest_format, native_format)) { + return spice_bitmap_to_pixman(dest_image, + src_format, + flags, width,height, + src, src_stride, + palette_surface_format, palette); + } + + src_image = spice_bitmap_try_as_pixman(src_format, + flags, width,height, + src, src_stride); + + /* Can't convert directly, need a temporary copy + * Hopefully most bitmap reads should not need conversion (i.e. + * hit the spice_bitmap_to_pixmap case above) or work with the + * try_as_pixmap case, but in case some specific combination + * shows up here commonly we might want to add non-temporary + * conversion special casing here */ + if (src_image == NULL) { + src_image = spice_bitmap_to_pixman(NULL, + src_format, + flags, width,height, + src, src_stride, + palette_surface_format, palette); + } + + pixman_image_composite32 (PIXMAN_OP_SRC, + src_image, NULL, dest_image, + 0, 0, + 0, 0, + 0, 0, + width, height); + + pixman_image_unref (src_image); + + return dest_image; +} diff --git a/spice-common/common/pixman_utils.h b/spice-common/common/pixman_utils.h new file mode 100644 index 0000000..f892777 --- /dev/null +++ b/spice-common/common/pixman_utils.h @@ -0,0 +1,143 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H__PIXMAN_UTILS +#define _H__PIXMAN_UTILS + +#include +#include +#include +#define PIXMAN_DONT_DEFINE_STDINT +#include + +#include "draw.h" + +#ifdef WORDS_BIGENDIAN +# define PIXMAN_LE_x8r8g8b8 PIXMAN_b8g8r8x8 +# define PIXMAN_LE_a8r8g8b8 PIXMAN_b8g8r8a8 +# define PIXMAN_LE_r8g8b8 PIXMAN_b8g8r8 +#else +# define PIXMAN_LE_x8r8g8b8 PIXMAN_x8r8g8b8 +# define PIXMAN_LE_a8r8g8b8 PIXMAN_a8r8g8b8 +# define PIXMAN_LE_r8g8b8 PIXMAN_r8g8b8 +#endif + +SPICE_BEGIN_DECLS + +/* This lists all possible 2 argument binary raster ops. + * This enum has the same values as the X11 GXcopy type + * and same as the GL constants (GL_AND etc) if you + * or it with 0x1500. However it is not exactly the + * same as the win32 ROP2 type (they use another order). + */ +typedef enum { + SPICE_ROP_CLEAR, /* 0x0 0 */ + SPICE_ROP_AND, /* 0x1 src AND dst */ + SPICE_ROP_AND_REVERSE, /* 0x2 src AND NOT dst */ + SPICE_ROP_COPY, /* 0x3 src */ + SPICE_ROP_AND_INVERTED, /* 0x4 (NOT src) AND dst */ + SPICE_ROP_NOOP, /* 0x5 dst */ + SPICE_ROP_XOR, /* 0x6 src XOR dst */ + SPICE_ROP_OR, /* 0x7 src OR dst */ + SPICE_ROP_NOR, /* 0x8 (NOT src) AND (NOT dst) */ + SPICE_ROP_EQUIV, /* 0x9 (NOT src) XOR dst */ + SPICE_ROP_INVERT, /* 0xa NOT dst */ + SPICE_ROP_OR_REVERSE, /* 0xb src OR (NOT dst) */ + SPICE_ROP_COPY_INVERTED, /* 0xc NOT src */ + SPICE_ROP_OR_INVERTED, /* 0xd (NOT src) OR dst */ + SPICE_ROP_NAND, /* 0xe (NOT src) OR (NOT dst) */ + SPICE_ROP_SET /* 0xf 1 */ +} SpiceROP; + + +int spice_pixman_image_get_bpp(pixman_image_t *image); + +pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format); +pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format, + uint32_t palette_surface_format); +pixman_image_t *spice_bitmap_try_as_pixman(int src_format, int flags, + int width, int height, + uint8_t *data, int stride); +pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image, + int src_format, int flags, + int width, int height, + uint8_t *src, int src_stride, + uint32_t palette_surface_format, + SpicePalette *palette); +pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format, + pixman_image_t *dest_image, + int src_format, int flags, + int width, int height, + uint8_t *src, int src_stride, + uint32_t palette_surface_format, + SpicePalette *palette); + +void spice_pixman_region32_init_from_bitmap(pixman_region32_t *region, + uint32_t *data, + int width, int height, + int stride); +pixman_bool_t spice_pixman_region32_init_rects(pixman_region32_t *region, + const SpiceRect *rects, + int count); +void spice_pixman_fill_rect(pixman_image_t *dest, + int x, int y, + int w, int h, + uint32_t value); +void spice_pixman_fill_rect_rop(pixman_image_t *dest, + int x, int y, + int w, int h, + uint32_t value, + SpiceROP rop); +void spice_pixman_tile_rect(pixman_image_t *dest, + int x, int y, + int w, int h, + pixman_image_t *tile, + int offset_x, + int offset_y); +void spice_pixman_tile_rect_rop(pixman_image_t *dest, + int x, int y, + int w, int h, + pixman_image_t *tile, + int offset_x, + int offset_y, + SpiceROP rop); +void spice_pixman_blit(pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int w, int h); +void spice_pixman_blit_rop(pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int w, int h, + SpiceROP rop); +void spice_pixman_blit_colorkey(pixman_image_t *dest, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + uint32_t transparent_color); +void spice_pixman_copy_rect(pixman_image_t *image, + int src_x, int src_y, + int w, int h, + int dest_x, int dest_y); + +SPICE_END_DECLS + +#endif /* _H__PIXMAN_UTILS */ diff --git a/spice-common/common/quic.c b/spice-common/common/quic.c new file mode 100644 index 0000000..f014a2a --- /dev/null +++ b/spice-common/common/quic.c @@ -0,0 +1,1676 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +// Red Hat image compression based on SFALIC by Roman Starosolski +// http://sun.iinf.polsl.gliwice.pl/~rstaros/sfalic/index.html + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "quic.h" +#include "spice_common.h" +#include "bitops.h" + +#define RLE +#define RLE_STAT +#define PRED_1 +//#define RLE_PRED_1 +#define RLE_PRED_2 +//#define RLE_PRED_3 +#define QUIC_RGB + +/* ASCII "QUIC" */ +#define QUIC_MAGIC 0x43495551 +#define QUIC_VERSION_MAJOR 0U +#define QUIC_VERSION_MINOR 1U +#define QUIC_VERSION ((QUIC_VERSION_MAJOR << 16) | (QUIC_VERSION_MAJOR & 0xffff)) + +typedef uint8_t BYTE; + +/* maximum number of codes in family */ +#define MAXNUMCODES 8 + +/* model evolution, warning: only 1,3 and 5 allowed */ +#define DEFevol 3 +#define MINevol 0 +#define MAXevol 5 + +/* starting wait mask index */ +#define DEFwmistart 0 +#define MINwmistart 0 + +/* codeword length limit */ +#define DEFmaxclen 26 + +/* target wait mask index */ +#define DEFwmimax 6 + +/* number of symbols to encode before increasing wait mask index */ +#define DEFwminext 2048 +#define MINwminext 1 +#define MAXwminext 100000000 + +typedef struct QuicFamily { + unsigned int nGRcodewords[MAXNUMCODES]; /* indexed by code number, contains number of + unmodified GR codewords in the code */ + unsigned int notGRcwlen[MAXNUMCODES]; /* indexed by code number, contains codeword + length of the not-GR codeword */ + unsigned int notGRprefixmask[MAXNUMCODES]; /* indexed by code number, contains mask to + determine if the codeword is GR or not-GR */ + unsigned int notGRsuffixlen[MAXNUMCODES]; /* indexed by code number, contains suffix + length of the not-GR codeword */ + + unsigned int golomb_code_len[256][MAXNUMCODES]; + unsigned int golomb_code[256][MAXNUMCODES]; + + /* array for translating distribution U to L for depths up to 8 bpp, + initialized by decorelateinit() */ + BYTE xlatU2L[256]; + + /* array for translating distribution L to U for depths up to 8 bpp, + initialized by corelateinit() */ + unsigned int xlatL2U[256]; +} QuicFamily; + +static QuicFamily family_8bpc; +static QuicFamily family_5bpc; + +typedef unsigned COUNTER; /* counter in the array of counters in bucket of the data model */ + +typedef struct s_bucket { + COUNTER *pcounters; /* pointer to array of counters */ + unsigned int bestcode; /* best code so far */ +} s_bucket; + +typedef struct Encoder Encoder; + +typedef struct CommonState { + Encoder *encoder; + + unsigned int waitcnt; + unsigned int tabrand_seed; + unsigned int wm_trigger; + unsigned int wmidx; + unsigned int wmileft; + +#ifdef RLE_STAT + int melcstate; /* index to the state array */ + + int melclen; /* contents of the state array location + indexed by melcstate: the "expected" + run length is 2^melclen, shorter runs are + encoded by a 1 followed by the run length + in binary representation, wit a fixed length + of melclen bits */ + + unsigned long melcorder; /* 2^ melclen */ +#endif +} CommonState; + + +#define MAX_CHANNELS 4 + +typedef struct FamilyStat { + s_bucket **buckets_ptrs; + s_bucket *buckets_buf; + COUNTER *counters; +} FamilyStat; + +typedef struct Channel { + Encoder *encoder; + + int correlate_row_width; + BYTE *correlate_row; + + s_bucket **_buckets_ptrs; + + FamilyStat family_stat_8bpc; + FamilyStat family_stat_5bpc; + + CommonState state; +} Channel; + +struct Encoder { + QuicUsrContext *usr; + QuicImageType type; + unsigned int width; + unsigned int height; + unsigned int num_channels; + + unsigned int n_buckets_8bpc; + unsigned int n_buckets_5bpc; + + unsigned int io_available_bits; + uint32_t io_word; + uint32_t io_next_word; + uint32_t *io_now; + uint32_t *io_end; + uint32_t io_words_count; + + int rows_completed; + + Channel channels[MAX_CHANNELS]; + + CommonState rgb_state; +}; + +/* target wait mask index */ +static int wmimax = DEFwmimax; + +/* number of symbols to encode before increasing wait mask index */ +static int wminext = DEFwminext; + +/* model evolution mode */ +static int evol = DEFevol; + +/* bppmask[i] contains i ones as lsb-s */ +static const unsigned long int bppmask[33] = { + 0x00000000, /* [0] */ + 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, + 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, + 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, + 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, + 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, + 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, + 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff /* [32] */ +}; + +#define bitat(n) (1u<<(n)) + + +#define TABRAND_TABSIZE 256 +#define TABRAND_SEEDMASK 0x0ff + +static const unsigned int tabrand_chaos[TABRAND_TABSIZE] = { + 0x02c57542, 0x35427717, 0x2f5a2153, 0x9244f155, 0x7bd26d07, 0x354c6052, 0x57329b28, 0x2993868e, + 0x6cd8808c, 0x147b46e0, 0x99db66af, 0xe32b4cac, 0x1b671264, 0x9d433486, 0x62a4c192, 0x06089a4b, + 0x9e3dce44, 0xdaabee13, 0x222425ea, 0xa46f331d, 0xcd589250, 0x8bb81d7f, 0xc8b736b9, 0x35948d33, + 0xd7ac7fd0, 0x5fbe2803, 0x2cfbc105, 0x013dbc4e, 0x7a37820f, 0x39f88e9e, 0xedd58794, 0xc5076689, + 0xfcada5a4, 0x64c2f46d, 0xb3ba3243, 0x8974b4f9, 0x5a05aebd, 0x20afcd00, 0x39e2b008, 0x88a18a45, + 0x600bde29, 0xf3971ace, 0xf37b0a6b, 0x7041495b, 0x70b707ab, 0x06beffbb, 0x4206051f, 0xe13c4ee3, + 0xc1a78327, 0x91aa067c, 0x8295f72a, 0x732917a6, 0x1d871b4d, 0x4048f136, 0xf1840e7e, 0x6a6048c1, + 0x696cb71a, 0x7ff501c3, 0x0fc6310b, 0x57e0f83d, 0x8cc26e74, 0x11a525a2, 0x946934c7, 0x7cd888f0, + 0x8f9d8604, 0x4f86e73b, 0x04520316, 0xdeeea20c, 0xf1def496, 0x67687288, 0xf540c5b2, 0x22401484, + 0x3478658a, 0xc2385746, 0x01979c2c, 0x5dad73c8, 0x0321f58b, 0xf0fedbee, 0x92826ddf, 0x284bec73, + 0x5b1a1975, 0x03df1e11, 0x20963e01, 0xa17cf12b, 0x740d776e, 0xa7a6bf3c, 0x01b5cce4, 0x1118aa76, + 0xfc6fac0a, 0xce927e9b, 0x00bf2567, 0x806f216c, 0xbca69056, 0x795bd3e9, 0xc9dc4557, 0x8929b6c2, + 0x789d52ec, 0x3f3fbf40, 0xb9197368, 0xa38c15b5, 0xc3b44fa8, 0xca8333b0, 0xb7e8d590, 0xbe807feb, + 0xbf5f8360, 0xd99e2f5c, 0x372928e1, 0x7c757c4c, 0x0db5b154, 0xc01ede02, 0x1fc86e78, 0x1f3985be, + 0xb4805c77, 0x00c880fa, 0x974c1b12, 0x35ab0214, 0xb2dc840d, 0x5b00ae37, 0xd313b026, 0xb260969d, + 0x7f4c8879, 0x1734c4d3, 0x49068631, 0xb9f6a021, 0x6b863e6f, 0xcee5debf, 0x29f8c9fb, 0x53dd6880, + 0x72b61223, 0x1f67a9fd, 0x0a0f6993, 0x13e59119, 0x11cca12e, 0xfe6b6766, 0x16b6effc, 0x97918fc4, + 0xc2b8a563, 0x94f2f741, 0x0bfa8c9a, 0xd1537ae8, 0xc1da349c, 0x873c60ca, 0x95005b85, 0x9b5c080e, + 0xbc8abbd9, 0xe1eab1d2, 0x6dac9070, 0x4ea9ebf1, 0xe0cf30d4, 0x1ef5bd7b, 0xd161043e, 0x5d2fa2e2, + 0xff5d3cae, 0x86ed9f87, 0x2aa1daa1, 0xbd731a34, 0x9e8f4b22, 0xb1c2c67a, 0xc21758c9, 0xa182215d, + 0xccb01948, 0x8d168df7, 0x04238cfe, 0x368c3dbc, 0x0aeadca5, 0xbad21c24, 0x0a71fee5, 0x9fc5d872, + 0x54c152c6, 0xfc329483, 0x6783384a, 0xeddb3e1c, 0x65f90e30, 0x884ad098, 0xce81675a, 0x4b372f7d, + 0x68bf9a39, 0x43445f1e, 0x40f8d8cb, 0x90d5acb6, 0x4cd07282, 0x349eeb06, 0x0c9d5332, 0x520b24ef, + 0x80020447, 0x67976491, 0x2f931ca3, 0xfe9b0535, 0xfcd30220, 0x61a9e6cc, 0xa487d8d7, 0x3f7c5dd1, + 0x7d0127c5, 0x48f51d15, 0x60dea871, 0xc9a91cb7, 0x58b53bb3, 0x9d5e0b2d, 0x624a78b4, 0x30dbee1b, + 0x9bdf22e7, 0x1df5c299, 0x2d5643a7, 0xf4dd35ff, 0x03ca8fd6, 0x53b47ed8, 0x6f2c19aa, 0xfeb0c1f4, + 0x49e54438, 0x2f2577e6, 0xbf876969, 0x72440ea9, 0xfa0bafb8, 0x74f5b3a0, 0x7dd357cd, 0x89ce1358, + 0x6ef2cdda, 0x1e7767f3, 0xa6be9fdb, 0x4f5f88f8, 0xba994a3a, 0x08ca6b65, 0xe0893818, 0x9e00a16a, + 0xf42bfc8f, 0x9972eedc, 0x749c8b51, 0x32c05f5e, 0xd706805f, 0x6bfbb7cf, 0xd9210a10, 0x31a1db97, + 0x923a9559, 0x37a7a1f6, 0x059f8861, 0xca493e62, 0x65157e81, 0x8f6467dd, 0xab85ff9f, 0x9331aff2, + 0x8616b9f5, 0xedbd5695, 0xee7e29b1, 0x313ac44f, 0xb903112f, 0x432ef649, 0xdc0a36c0, 0x61cf2bba, + 0x81474925, 0xa8b6c7ad, 0xee5931de, 0xb2f8158d, 0x59fb7409, 0x2e3dfaed, 0x9af25a3f, 0xe1fed4d5, +}; + +static unsigned int stabrand(void) +{ + //spice_assert( !(TABRAND_SEEDMASK & TABRAND_TABSIZE)); + //spice_assert( TABRAND_SEEDMASK + 1 == TABRAND_TABSIZE ); + + return TABRAND_SEEDMASK; +} + +static unsigned int tabrand(unsigned int *tabrand_seed) +{ + return tabrand_chaos[++*tabrand_seed & TABRAND_SEEDMASK]; +} + +static const unsigned short besttrigtab[3][11] = { /* array of wm_trigger for waitmask and evol, + used by set_wm_trigger() */ + /* 1 */ { 550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160}, + /* 3 */ { 110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140}, + /* 5 */ { 100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160} +}; + +/* set wm_trigger knowing waitmask (param) and evol (glob)*/ +static void set_wm_trigger(CommonState *state) +{ + unsigned int wm = state->wmidx; + if (wm > 10) { + wm = 10; + } + + spice_assert(evol < 6); + + state->wm_trigger = besttrigtab[evol / 2][wm]; + + spice_assert(state->wm_trigger <= 2000); + spice_assert(state->wm_trigger >= 1); +} + +static int ceil_log_2(int val) /* ceil(log_2(val)) */ +{ + int result; + + //spice_assert(val>0); + + if (val == 1) { + return 0; + } + + result = 1; + val -= 1; + while (val >>= 1) { + result++; + } + + return result; +} + +/* number of leading zeroes in the byte, used by cntlzeroes(uint)*/ +static const BYTE lzeroes[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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 +}; + +/* count leading zeroes */ +static unsigned int cnt_l_zeroes(const unsigned int bits) +{ + if (bits & 0xff800000) { + return lzeroes[bits >> 24]; + } else if (bits & 0xffff8000) { + return 8 + lzeroes[(bits >> 16) & 0x000000ff]; + } else if (bits & 0xffffff80) { + return 16 + lzeroes[(bits >> 8) & 0x000000ff]; + } else { + return 24 + lzeroes[bits & 0x000000ff]; + } +} + +#define QUIC_FAMILY_8BPC +#include "quic_family_tmpl.c" + +#ifdef QUIC_RGB +#define QUIC_FAMILY_5BPC +#include "quic_family_tmpl.c" +#endif + +static void decorelate_init(QuicFamily *family, int bpc) +{ + const unsigned int pixelbitmask = bppmask[bpc]; + const unsigned int pixelbitmaskshr = pixelbitmask >> 1; + unsigned int s; + + //spice_assert(bpc <= 8); + + for (s = 0; s <= pixelbitmask; s++) { + if (s <= pixelbitmaskshr) { + family->xlatU2L[s] = s << 1; + } else { + family->xlatU2L[s] = ((pixelbitmask - s) << 1) + 1; + } + } +} + +static void corelate_init(QuicFamily *family, int bpc) +{ + const unsigned long int pixelbitmask = bppmask[bpc]; + unsigned long int s; + + //spice_assert(bpc <= 8); + + for (s = 0; s <= pixelbitmask; s++) { + if (s & 0x01) { + family->xlatL2U[s] = pixelbitmask - (s >> 1); + } else { + family->xlatL2U[s] = (s >> 1); + } + } +} + +static void golomb_coding_slow(QuicFamily *family, const BYTE n, const unsigned int l, + unsigned int * const codeword, + unsigned int * const codewordlen) +{ + if (n < family->nGRcodewords[l]) { + (*codeword) = bitat(l) | (n & bppmask[l]); + (*codewordlen) = (n >> l) + l + 1; + } else { + (*codeword) = n - family->nGRcodewords[l]; + (*codewordlen) = family->notGRcwlen[l]; + } +} + +static void family_init(QuicFamily *family, int bpc, int limit) +{ + int l, b; + + for (l = 0; l < bpc; l++) { /* fill arrays indexed by code number */ + int altprefixlen, altcodewords; + + altprefixlen = limit - bpc; + if (altprefixlen > (int)(bppmask[bpc - l])) { + altprefixlen = bppmask[bpc - l]; + } + + altcodewords = bppmask[bpc] + 1 - (altprefixlen << l); + + family->nGRcodewords[l] = (altprefixlen << l); + family->notGRsuffixlen[l] = ceil_log_2(altcodewords); /* needed for decoding only */ + family->notGRcwlen[l] = altprefixlen + family->notGRsuffixlen[l]; + family->notGRprefixmask[l] = bppmask[32 - altprefixlen]; /* needed for decoding only */ + + for (b = 0; b < 256; b++) { + unsigned int code, len; + golomb_coding_slow(family, b, l, &code, &len); + family->golomb_code[b][l] = code; + family->golomb_code_len[b][l] = len; + } + } + + decorelate_init(family, bpc); + corelate_init(family, bpc); +} + +static void more_io_words(Encoder *encoder) +{ + uint32_t *io_ptr; + int num_io_words = encoder->usr->more_space(encoder->usr, &io_ptr, encoder->rows_completed); + if (num_io_words <= 0) { + encoder->usr->error(encoder->usr, "%s: no more words\n", __FUNCTION__); + } + spice_assert(io_ptr); + encoder->io_words_count += num_io_words; + encoder->io_now = io_ptr; + encoder->io_end = encoder->io_now + num_io_words; +} + +static void __write_io_word(Encoder *encoder) +{ + more_io_words(encoder); + *(encoder->io_now++) = encoder->io_word; +} + +static void (*__write_io_word_ptr)(Encoder *encoder) = __write_io_word; + +static inline void write_io_word(Encoder *encoder) +{ + if (encoder->io_now == encoder->io_end) { + __write_io_word_ptr(encoder); //disable inline optimizations + return; + } + *(encoder->io_now++) = encoder->io_word; +} + +static inline void encode(Encoder *encoder, unsigned int word, unsigned int len) +{ + int delta; + + spice_assert(len > 0 && len < 32); + spice_assert(!(word & ~bppmask[len])); + if ((delta = ((int)encoder->io_available_bits - len)) >= 0) { + encoder->io_available_bits = delta; + encoder->io_word |= word << encoder->io_available_bits; + return; + } + delta = -delta; + encoder->io_word |= word >> delta; + write_io_word(encoder); + encoder->io_available_bits = 32 - delta; + encoder->io_word = word << encoder->io_available_bits; + + spice_assert(encoder->io_available_bits < 32); + spice_assert((encoder->io_word & bppmask[encoder->io_available_bits]) == 0); +} + +static inline void encode_32(Encoder *encoder, unsigned int word) +{ + encode(encoder, word >> 16, 16); + encode(encoder, word & 0x0000ffff, 16); +} + +static inline void flush(Encoder *encoder) +{ + if (encoder->io_available_bits > 0 && encoder->io_available_bits != 32) { + encode(encoder, 0, encoder->io_available_bits); + } + encode_32(encoder, 0); + encode(encoder, 0, 1); +} + +static void __read_io_word(Encoder *encoder) +{ + more_io_words(encoder); + encoder->io_next_word = GUINT32_FROM_LE(*(encoder->io_now++)); +} + +static void (*__read_io_word_ptr)(Encoder *encoder) = __read_io_word; + + +static inline void read_io_word(Encoder *encoder) +{ + if (encoder->io_now == encoder->io_end) { + __read_io_word_ptr(encoder); //disable inline optimizations + return; + } + spice_assert(encoder->io_now < encoder->io_end); + encoder->io_next_word = GUINT32_FROM_LE(*(encoder->io_now++)); +} + +static inline void decode_eatbits(Encoder *encoder, int len) +{ + int delta; + + spice_assert(len > 0 && len < 32); + encoder->io_word <<= len; + + if ((delta = ((int)encoder->io_available_bits - len)) >= 0) { + encoder->io_available_bits = delta; + encoder->io_word |= encoder->io_next_word >> encoder->io_available_bits; + return; + } + + delta = -delta; + encoder->io_word |= encoder->io_next_word << delta; + read_io_word(encoder); + encoder->io_available_bits = 32 - delta; + encoder->io_word |= (encoder->io_next_word >> encoder->io_available_bits); +} + +static inline void decode_eat32bits(Encoder *encoder) +{ + decode_eatbits(encoder, 16); + decode_eatbits(encoder, 16); +} + +#ifdef RLE + +#ifdef RLE_STAT + +static inline void encode_ones(Encoder *encoder, unsigned int n) +{ + unsigned int count; + + for (count = n >> 5; count; count--) { + encode(encoder, ~0U, 32); + } + + if ((n &= 0x1f)) { + encode(encoder, (1U << n) - 1, n); + } +} + +#define MELCSTATES 32 /* number of melcode states */ + +static const int J[MELCSTATES] = { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static void encoder_init_rle(CommonState *state) +{ + state->melcstate = 0; + state->melclen = J[0]; + state->melcorder = 1 << state->melclen; +} + +#ifdef QUIC_RGB + +static void encode_run(Encoder *encoder, unsigned int runlen) //todo: try use end of line +{ + int hits = 0; + + while (runlen >= encoder->rgb_state.melcorder) { + hits++; + runlen -= encoder->rgb_state.melcorder; + if (encoder->rgb_state.melcstate < MELCSTATES - 1) { + encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate]; + encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen); + } + } + + /* send the required number of "hit" bits (one per occurrence + of a run of length melcorder). This number is never too big: + after 31 such "hit" bits, each "hit" would represent a run of 32K + pixels. + */ + encode_ones(encoder, hits); + + encode(encoder, runlen, encoder->rgb_state.melclen + 1); + + /* adjust melcoder parameters */ + if (encoder->rgb_state.melcstate) { + encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate]; + encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen); + } +} + +#endif + +static void encode_channel_run(Encoder *encoder, Channel *channel, unsigned int runlen) +{ + //todo: try use end of line + int hits = 0; + + while (runlen >= channel->state.melcorder) { + hits++; + runlen -= channel->state.melcorder; + if (channel->state.melcstate < MELCSTATES - 1) { + channel->state.melclen = J[++channel->state.melcstate]; + channel->state.melcorder = (1L << channel->state.melclen); + } + } + + /* send the required number of "hit" bits (one per occurrence + of a run of length melcorder). This number is never too big: + after 31 such "hit" bits, each "hit" would represent a run of 32K + pixels. + */ + encode_ones(encoder, hits); + + encode(encoder, runlen, channel->state.melclen + 1); + + /* adjust melcoder parameters */ + if (channel->state.melcstate) { + channel->state.melclen = J[--channel->state.melcstate]; + channel->state.melcorder = (1L << channel->state.melclen); + } +} + +/* decoding routine: reads bits from the input and returns a run length. */ +/* argument is the number of pixels left to end-of-line (bound on run length) */ + +#ifdef QUIC_RGB +static int decode_run(Encoder *encoder) +{ + int runlen = 0; + + do { + register int temp, hits; + temp = lzeroes[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the + input stream, up to 8 */ + for (hits = 1; hits <= temp; hits++) { + runlen += encoder->rgb_state.melcorder; + + if (encoder->rgb_state.melcstate < MELCSTATES - 1) { + encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate]; + encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen); + } + } + if (temp != 8) { + decode_eatbits(encoder, temp + 1); /* consume the leading + 0 of the remainder encoding */ + break; + } + decode_eatbits(encoder, 8); + } while (1); + + /* read the length of the remainder */ + if (encoder->rgb_state.melclen) { + runlen += encoder->io_word >> (32 - encoder->rgb_state.melclen); + decode_eatbits(encoder, encoder->rgb_state.melclen); + } + + /* adjust melcoder parameters */ + if (encoder->rgb_state.melcstate) { + encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate]; + encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen); + } + + return runlen; +} + +#endif + +static int decode_channel_run(Encoder *encoder, Channel *channel) +{ + int runlen = 0; + + do { + register int temp, hits; + temp = lzeroes[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the + input stream, up to 8 */ + for (hits = 1; hits <= temp; hits++) { + runlen += channel->state.melcorder; + + if (channel->state.melcstate < MELCSTATES - 1) { + channel->state.melclen = J[++channel->state.melcstate]; + channel->state.melcorder = (1U << channel->state.melclen); + } + } + if (temp != 8) { + decode_eatbits(encoder, temp + 1); /* consume the leading + 0 of the remainder encoding */ + break; + } + decode_eatbits(encoder, 8); + } while (1); + + /* read the length of the remainder */ + if (channel->state.melclen) { + runlen += encoder->io_word >> (32 - channel->state.melclen); + decode_eatbits(encoder, channel->state.melclen); + } + + /* adjust melcoder parameters */ + if (channel->state.melcstate) { + channel->state.melclen = J[--channel->state.melcstate]; + channel->state.melcorder = (1U << channel->state.melclen); + } + + return runlen; +} + +#else + +static inline void encode_run(Encoder *encoder, unsigned int len) +{ + int odd = len & 1U; + int msb; + + len &= ~1U; + + while ((msb = spice_bit_find_msb(len))) { + len &= ~(1 << (msb - 1)); + spice_assert(msb < 32); + encode(encoder, (1 << (msb)) - 1, msb); + encode(encoder, 0, 1); + } + + if (odd) { + encode(encoder, 2, 2); + } else { + encode(encoder, 0, 1); + } +} + +static inline unsigned int decode_run(Encoder *encoder) +{ + unsigned int len = 0; + int count; + + do { + count = 0; + while (encoder->io_word & (1U << 31)) { + decode_eatbits(encoder, 1); + count++; + spice_assert(count < 32); + } + decode_eatbits(encoder, 1); + len += (1U << count) >> 1; + } while (count > 1); + + return len; +} + +#endif +#endif + +static inline void init_decode_io(Encoder *encoder) +{ + encoder->io_next_word = encoder->io_word = GUINT32_FROM_LE(*(encoder->io_now++)); + encoder->io_available_bits = 0; +} + +#ifdef __GNUC__ +#define ATTR_PACKED __attribute__ ((__packed__)) +#else +#define ATTR_PACKED +#pragma pack(push) +#pragma pack(1) +#endif + +typedef struct ATTR_PACKED one_byte_pixel_t { + BYTE a; +} one_byte_t; + +typedef struct ATTR_PACKED three_bytes_pixel_t { + BYTE a; + BYTE b; + BYTE c; +} three_bytes_t; + +typedef struct ATTR_PACKED four_bytes_pixel_t { + BYTE a; + BYTE b; + BYTE c; + BYTE d; +} four_bytes_t; + +typedef struct ATTR_PACKED rgb32_pixel_t { + BYTE b; + BYTE g; + BYTE r; + BYTE pad; +} rgb32_pixel_t; + +typedef struct ATTR_PACKED rgb24_pixel_t { + BYTE b; + BYTE g; + BYTE r; +} rgb24_pixel_t; + +typedef uint16_t rgb16_pixel_t; + +#ifndef __GNUC__ +#pragma pack(pop) +#endif + +#undef ATTR_PACKED + +#define ONE_BYTE +#include "quic_tmpl.c" + +#define FOUR_BYTE +#include "quic_tmpl.c" + +#ifdef QUIC_RGB + +#define QUIC_RGB32 +#include "quic_rgb_tmpl.c" + +#define QUIC_RGB24 +#include "quic_rgb_tmpl.c" + +#define QUIC_RGB16 +#include "quic_rgb_tmpl.c" + +#define QUIC_RGB16_TO_32 +#include "quic_rgb_tmpl.c" + +#else + +#define THREE_BYTE +#include "quic_tmpl.c" + +#endif + +static void fill_model_structures(SPICE_GNUC_UNUSED Encoder *encoder, FamilyStat *family_stat, + unsigned int rep_first, unsigned int first_size, + unsigned int rep_next, unsigned int mul_size, + unsigned int levels, unsigned int ncounters, + unsigned int nbuckets, unsigned int n_buckets_ptrs) +{ + unsigned int + bsize, + bstart, + bend = 0, + repcntr, + bnumber; + + COUNTER * free_counter = family_stat->counters;/* first free location in the array of + counters */ + + bnumber = 0; + + repcntr = rep_first + 1; /* first bucket */ + bsize = first_size; + + do { /* others */ + if (bnumber) { + bstart = bend + 1; + } else { + bstart = 0; + } + + if (!--repcntr) { + repcntr = rep_next; + bsize *= mul_size; + } + + bend = bstart + bsize - 1; + if (bend + bsize >= levels) { + bend = levels - 1; + } + + family_stat->buckets_buf[bnumber].pcounters = free_counter; + free_counter += ncounters; + + spice_assert(bstart < n_buckets_ptrs); + { + unsigned int i; + spice_assert(bend < n_buckets_ptrs); + for (i = bstart; i <= bend; i++) { + family_stat->buckets_ptrs[i] = family_stat->buckets_buf + bnumber; + } + } + + bnumber++; + } while (bend < levels - 1); + + spice_assert(free_counter - family_stat->counters == nbuckets * ncounters); +} + +static void find_model_params(Encoder *encoder, + const int bpc, + unsigned int *ncounters, + unsigned int *levels, + unsigned int *n_buckets_ptrs, + unsigned int *repfirst, + unsigned int *firstsize, + unsigned int *repnext, + unsigned int *mulsize, + unsigned int *nbuckets) +{ + unsigned int bsize; /* bucket size */ + unsigned int bstart, bend = 0; /* bucket start and end, range : 0 to levels-1*/ + unsigned int repcntr; /* helper */ + + /* The only valid values are 1, 3 and 5. + 0, 2 and 4 are obsolete and the rest of the + values are considered out of the range. */ + spice_static_assert (evol == 1 || evol == 3 || evol == 5); + spice_assert(bpc <= 8 && bpc > 0); + + *ncounters = 8; + + *levels = 0x1 << bpc; + + *n_buckets_ptrs = 0; /* ==0 means: not set yet */ + + switch (evol) { /* set repfirst firstsize repnext mulsize */ + case 1: /* buckets contain following numbers of contexts: 1 1 1 2 2 4 4 8 8 ... */ + *repfirst = 3; + *firstsize = 1; + *repnext = 2; + *mulsize = 2; + break; + case 3: /* 1 2 4 8 16 32 64 ... */ + *repfirst = 1; + *firstsize = 1; + *repnext = 1; + *mulsize = 2; + break; + case 5: /* 1 4 16 64 256 1024 4096 16384 65536 */ + *repfirst = 1; + *firstsize = 1; + *repnext = 1; + *mulsize = 4; + break; + default: + encoder->usr->error(encoder->usr, "findmodelparams(): evol out of range!!!\n"); + return; + } + + *nbuckets = 0; + repcntr = *repfirst + 1; /* first bucket */ + bsize = *firstsize; + + do { /* other buckets */ + if (*nbuckets) { /* bucket start */ + bstart = bend + 1; + } else { + bstart = 0; + } + + if (!--repcntr) { /* bucket size */ + repcntr = *repnext; + bsize *= *mulsize; + } + + bend = bstart + bsize - 1; /* bucket end */ + if (bend + bsize >= *levels) { /* if following bucked was bigger than current one */ + bend = *levels - 1; /* concatenate them */ + } + + if (!*n_buckets_ptrs) { /* array size not set yet? */ + *n_buckets_ptrs = *levels; + #if 0 + if (bend == *levels - 1) { /* this bucket is last - all in the first array */ + *n_buckets_ptrs = *levels; + } else if (bsize >= 256) { /* this bucket is allowed to reside in the 2nd table */ + b_lo_ptrs = bstart; + spice_assert(bstart); /* previous bucket exists */ + } + #endif + } + + (*nbuckets)++; + } while (bend < *levels - 1); +} + +static int init_model_structures(Encoder *encoder, FamilyStat *family_stat, + unsigned int rep_first, unsigned int first_size, + unsigned int rep_next, unsigned int mul_size, + unsigned int levels, unsigned int ncounters, + unsigned int n_buckets_ptrs, unsigned int n_buckets) +{ + family_stat->buckets_ptrs = (s_bucket **)encoder->usr->malloc(encoder->usr, + n_buckets_ptrs * + sizeof(s_bucket *)); + if (!family_stat->buckets_ptrs) { + return FALSE; + } + + family_stat->counters = (COUNTER *)encoder->usr->malloc(encoder->usr, + n_buckets * sizeof(COUNTER) * + MAXNUMCODES); + if (!family_stat->counters) { + goto error_1; + } + + family_stat->buckets_buf = (s_bucket *)encoder->usr->malloc(encoder->usr, + n_buckets * sizeof(s_bucket)); + if (!family_stat->buckets_buf) { + goto error_2; + } + + fill_model_structures(encoder, family_stat, rep_first, first_size, rep_next, mul_size, levels, + ncounters, n_buckets, n_buckets_ptrs); + + return TRUE; + +error_2: + encoder->usr->free(encoder->usr, family_stat->counters); + +error_1: + encoder->usr->free(encoder->usr, family_stat->buckets_ptrs); + + return FALSE; +} + +static void free_family_stat(QuicUsrContext *usr, FamilyStat *family_stat) +{ + usr->free(usr, family_stat->buckets_ptrs); + usr->free(usr, family_stat->counters); + usr->free(usr, family_stat->buckets_buf); +} + +static int init_channel(Encoder *encoder, Channel *channel) +{ + unsigned int ncounters; + unsigned int levels; + unsigned int rep_first; + unsigned int first_size; + unsigned int rep_next; + unsigned int mul_size; + unsigned int n_buckets; + unsigned int n_buckets_ptrs; + + channel->encoder = encoder; + channel->state.encoder = encoder; + channel->correlate_row_width = 0; + channel->correlate_row = NULL; + + find_model_params(encoder, 8, &ncounters, &levels, &n_buckets_ptrs, &rep_first, + &first_size, &rep_next, &mul_size, &n_buckets); + encoder->n_buckets_8bpc = n_buckets; + if (!init_model_structures(encoder, &channel->family_stat_8bpc, rep_first, first_size, + rep_next, mul_size, levels, ncounters, n_buckets_ptrs, + n_buckets)) { + return FALSE; + } + + find_model_params(encoder, 5, &ncounters, &levels, &n_buckets_ptrs, &rep_first, + &first_size, &rep_next, &mul_size, &n_buckets); + encoder->n_buckets_5bpc = n_buckets; + if (!init_model_structures(encoder, &channel->family_stat_5bpc, rep_first, first_size, + rep_next, mul_size, levels, ncounters, n_buckets_ptrs, + n_buckets)) { + free_family_stat(encoder->usr, &channel->family_stat_8bpc); + return FALSE; + } + + return TRUE; +} + +static void destroy_channel(Channel *channel) +{ + QuicUsrContext *usr = channel->encoder->usr; + if (channel->correlate_row) { + usr->free(usr, channel->correlate_row - 1); + } + free_family_stat(usr, &channel->family_stat_8bpc); + free_family_stat(usr, &channel->family_stat_5bpc); +} + +static int init_encoder(Encoder *encoder, QuicUsrContext *usr) +{ + int i; + + encoder->usr = usr; + encoder->rgb_state.encoder = encoder; + + for (i = 0; i < MAX_CHANNELS; i++) { + if (!init_channel(encoder, &encoder->channels[i])) { + for (--i; i >= 0; i--) { + destroy_channel(&encoder->channels[i]); + } + return FALSE; + } + } + return TRUE; +} + +static int encoder_reste(Encoder *encoder, uint32_t *io_ptr, uint32_t *io_ptr_end) +{ + spice_assert(((unsigned long)io_ptr % 4) == ((unsigned long)io_ptr_end % 4)); + spice_assert(io_ptr <= io_ptr_end); + + encoder->rgb_state.waitcnt = 0; + encoder->rgb_state.tabrand_seed = stabrand(); + encoder->rgb_state.wmidx = DEFwmistart; + encoder->rgb_state.wmileft = wminext; + set_wm_trigger(&encoder->rgb_state); + +#if defined(RLE) && defined(RLE_STAT) + encoder_init_rle(&encoder->rgb_state); +#endif + + encoder->io_words_count = io_ptr_end - io_ptr; + encoder->io_now = io_ptr; + encoder->io_end = io_ptr_end; + encoder->rows_completed = 0; + + return TRUE; +} + +static int encoder_reste_channels(Encoder *encoder, int channels, int width, int bpc) +{ + int i; + + encoder->num_channels = channels; + + for (i = 0; i < channels; i++) { + s_bucket *bucket; + s_bucket *end_bucket; + + if (encoder->channels[i].correlate_row_width < width) { + encoder->channels[i].correlate_row_width = 0; + if (encoder->channels[i].correlate_row) { + encoder->usr->free(encoder->usr, encoder->channels[i].correlate_row - 1); + } + if (!(encoder->channels[i].correlate_row = (BYTE *)encoder->usr->malloc(encoder->usr, + width + 1))) { + return FALSE; + } + encoder->channels[i].correlate_row++; + encoder->channels[i].correlate_row_width = width; + } + + if (bpc == 8) { + MEMCLEAR(encoder->channels[i].family_stat_8bpc.counters, + encoder->n_buckets_8bpc * sizeof(COUNTER) * MAXNUMCODES); + bucket = encoder->channels[i].family_stat_8bpc.buckets_buf; + end_bucket = bucket + encoder->n_buckets_8bpc; + for (; bucket < end_bucket; bucket++) { + bucket->bestcode = /*BPC*/ 8 - 1; + } + encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_8bpc.buckets_ptrs; + } else if (bpc == 5) { + MEMCLEAR(encoder->channels[i].family_stat_5bpc.counters, + encoder->n_buckets_5bpc * sizeof(COUNTER) * MAXNUMCODES); + bucket = encoder->channels[i].family_stat_5bpc.buckets_buf; + end_bucket = bucket + encoder->n_buckets_5bpc; + for (; bucket < end_bucket; bucket++) { + bucket->bestcode = /*BPC*/ 5 - 1; + } + encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_5bpc.buckets_ptrs; + } else { + encoder->usr->warn(encoder->usr, "%s: bad bpc %d\n", __FUNCTION__, bpc); + return FALSE; + } + + encoder->channels[i].state.waitcnt = 0; + encoder->channels[i].state.tabrand_seed = stabrand(); + encoder->channels[i].state.wmidx = DEFwmistart; + encoder->channels[i].state.wmileft = wminext; + set_wm_trigger(&encoder->channels[i].state); + +#if defined(RLE) && defined(RLE_STAT) + encoder_init_rle(&encoder->channels[i].state); +#endif + } + return TRUE; +} + +static void quic_image_params(Encoder *encoder, QuicImageType type, int *channels, int *bpc) +{ + spice_assert(channels && bpc); + switch (type) { + case QUIC_IMAGE_TYPE_GRAY: + *channels = 1; + *bpc = 8; + break; + case QUIC_IMAGE_TYPE_RGB16: + *channels = 3; + *bpc = 5; +#ifndef QUIC_RGB + encoder->usr->error(encoder->usr, "not implemented\n"); +#endif + break; + case QUIC_IMAGE_TYPE_RGB24: + *channels = 3; + *bpc = 8; + break; + case QUIC_IMAGE_TYPE_RGB32: + *channels = 3; + *bpc = 8; + break; + case QUIC_IMAGE_TYPE_RGBA: + *channels = 4; + *bpc = 8; + break; + case QUIC_IMAGE_TYPE_INVALID: + default: + *channels = 0; + *bpc = 0; + encoder->usr->error(encoder->usr, "bad image type\n"); + } +} + +#define FILL_LINES() { \ + if (line == lines_end) { \ + int n = encoder->usr->more_lines(encoder->usr, &line); \ + if (n <= 0 || line == NULL) { \ + encoder->usr->error(encoder->usr, "more lines failed\n"); \ + } \ + lines_end = line + n * stride; \ + } \ +} + +#define NEXT_LINE() { \ + line += stride; \ + FILL_LINES(); \ +} + +#define QUIC_COMPRESS_RGB(bits) \ + encoder->channels[0].correlate_row[-1] = 0; \ + encoder->channels[1].correlate_row[-1] = 0; \ + encoder->channels[2].correlate_row[-1] = 0; \ + quic_rgb##bits##_compress_row0(encoder, (rgb##bits##_pixel_t *)(line), width); \ + encoder->rows_completed++; \ + for (row = 1; row < height; row++) { \ + prev = line; \ + NEXT_LINE(); \ + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \ + encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \ + encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \ + quic_rgb##bits##_compress_row(encoder, (rgb##bits##_pixel_t *)prev, \ + (rgb##bits##_pixel_t *)line, width); \ + encoder->rows_completed++; \ + } + +int quic_encode(QuicContext *quic, QuicImageType type, int width, int height, + uint8_t *line, unsigned int num_lines, int stride, + uint32_t *io_ptr, unsigned int num_io_words) +{ + Encoder *encoder = (Encoder *)quic; + uint32_t *io_ptr_end = io_ptr + num_io_words; + uint8_t *lines_end; + int row; + uint8_t *prev; + int channels; + int bpc; +#ifndef QUIC_RGB + int i; +#endif + + lines_end = line + num_lines * stride; + if (line == NULL && lines_end != line) { + spice_warn_if_reached(); + return QUIC_ERROR; + } + + quic_image_params(encoder, type, &channels, &bpc); + + if (!encoder_reste(encoder, io_ptr, io_ptr_end) || + !encoder_reste_channels(encoder, channels, width, bpc)) { + return QUIC_ERROR; + } + + encoder->io_word = 0; + encoder->io_available_bits = 32; + + encode_32(encoder, QUIC_MAGIC); + encode_32(encoder, QUIC_VERSION); + encode_32(encoder, type); + encode_32(encoder, width); + encode_32(encoder, height); + + FILL_LINES(); + + switch (type) { +#ifdef QUIC_RGB + case QUIC_IMAGE_TYPE_RGB32: + spice_assert(ABS(stride) >= width * 4); + QUIC_COMPRESS_RGB(32); + break; + case QUIC_IMAGE_TYPE_RGB24: + spice_assert(ABS(stride) >= width * 3); + QUIC_COMPRESS_RGB(24); + break; + case QUIC_IMAGE_TYPE_RGB16: + spice_assert(ABS(stride) >= width * 2); + QUIC_COMPRESS_RGB(16); + break; + case QUIC_IMAGE_TYPE_RGBA: + spice_assert(ABS(stride) >= width * 4); + + encoder->channels[0].correlate_row[-1] = 0; + encoder->channels[1].correlate_row[-1] = 0; + encoder->channels[2].correlate_row[-1] = 0; + quic_rgb32_compress_row0(encoder, (rgb32_pixel_t *)(line), width); + + encoder->channels[3].correlate_row[-1] = 0; + quic_four_compress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(line + 3), width); + + encoder->rows_completed++; + + for (row = 1; row < height; row++) { + prev = line; + NEXT_LINE(); + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; + encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; + encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; + quic_rgb32_compress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)line, width); + + encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0]; + quic_four_compress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3), + (four_bytes_t *)(line + 3), width); + encoder->rows_completed++; + } + break; +#else + case QUIC_IMAGE_TYPE_RGB24: + spice_assert(ABS(stride) >= width * 3); + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = 0; + quic_three_compress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(line + i), + width); + } + encoder->rows_completed++; + for (row = 1; row < height; row++) { + prev = line; + NEXT_LINE(); + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; + quic_three_compress_row(encoder, &encoder->channels[i], (three_bytes_t *)(prev + i), + (three_bytes_t *)(line + i), width); + } + encoder->rows_completed++; + } + break; + case QUIC_IMAGE_TYPE_RGB32: + case QUIC_IMAGE_TYPE_RGBA: + spice_assert(ABS(stride) >= width * 4); + for (i = 0; i < channels; i++) { + encoder->channels[i].correlate_row[-1] = 0; + quic_four_compress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(line + i), + width); + } + encoder->rows_completed++; + for (row = 1; row < height; row++) { + prev = line; + NEXT_LINE(); + for (i = 0; i < channels; i++) { + encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; + quic_four_compress_row(encoder, &encoder->channels[i], (four_bytes_t *)(prev + i), + (four_bytes_t *)(line + i), width); + } + encoder->rows_completed++; + } + break; +#endif + case QUIC_IMAGE_TYPE_GRAY: + spice_assert(ABS(stride) >= width); + encoder->channels[0].correlate_row[-1] = 0; + quic_one_compress_row0(encoder, &encoder->channels[0], (one_byte_t *)line, width); + encoder->rows_completed++; + for (row = 1; row < height; row++) { + prev = line; + NEXT_LINE(); + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; + quic_one_compress_row(encoder, &encoder->channels[0], (one_byte_t *)prev, + (one_byte_t *)line, width); + encoder->rows_completed++; + } + break; + case QUIC_IMAGE_TYPE_INVALID: + default: + encoder->usr->error(encoder->usr, "bad image type\n"); + } + + flush(encoder); + encoder->io_words_count -= (encoder->io_end - encoder->io_now); + + return encoder->io_words_count; +} + +int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words, + QuicImageType *out_type, int *out_width, int *out_height) +{ + Encoder *encoder = (Encoder *)quic; + uint32_t *io_ptr_end = io_ptr + num_io_words; + QuicImageType type; + int width; + int height; + uint32_t magic; + uint32_t version; + int channels; + int bpc; + + if (!encoder_reste(encoder, io_ptr, io_ptr_end)) { + return QUIC_ERROR; + } + + init_decode_io(encoder); + + magic = encoder->io_word; + decode_eat32bits(encoder); + if (magic != QUIC_MAGIC) { + encoder->usr->warn(encoder->usr, "bad magic\n"); + return QUIC_ERROR; + } + + version = encoder->io_word; + decode_eat32bits(encoder); + if (version != QUIC_VERSION) { + encoder->usr->warn(encoder->usr, "bad version\n"); + return QUIC_ERROR; + } + + type = (QuicImageType)encoder->io_word; + decode_eat32bits(encoder); + + width = encoder->io_word; + decode_eat32bits(encoder); + + height = encoder->io_word; + decode_eat32bits(encoder); + + quic_image_params(encoder, type, &channels, &bpc); + + if (!encoder_reste_channels(encoder, channels, width, bpc)) { + return QUIC_ERROR; + } + + *out_width = encoder->width = width; + *out_height = encoder->height = height; + *out_type = encoder->type = type; + return QUIC_OK; +} + +#ifndef QUIC_RGB +static void clear_row(four_bytes_t *row, int width) +{ + four_bytes_t *end; + for (end = row + width; row < end; row++) { + row->a = 0; + } +} + +#endif + +#ifdef QUIC_RGB + +static void uncompress_rgba(Encoder *encoder, uint8_t *buf, int stride) +{ + unsigned int row; + uint8_t *prev; + + encoder->channels[0].correlate_row[-1] = 0; + encoder->channels[1].correlate_row[-1] = 0; + encoder->channels[2].correlate_row[-1] = 0; + quic_rgb32_uncompress_row0(encoder, (rgb32_pixel_t *)buf, encoder->width); + + encoder->channels[3].correlate_row[-1] = 0; + quic_four_uncompress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(buf + 3), + encoder->width); + + encoder->rows_completed++; + for (row = 1; row < encoder->height; row++) { + prev = buf; + buf += stride; + + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; + encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; + encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; + quic_rgb32_uncompress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)buf, + encoder->width); + + encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0]; + quic_four_uncompress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3), + (four_bytes_t *)(buf + 3), encoder->width); + + encoder->rows_completed++; + } +} + +#endif + +static void uncompress_gray(Encoder *encoder, uint8_t *buf, int stride) +{ + unsigned int row; + uint8_t *prev; + + encoder->channels[0].correlate_row[-1] = 0; + quic_one_uncompress_row0(encoder, &encoder->channels[0], (one_byte_t *)buf, encoder->width); + encoder->rows_completed++; + for (row = 1; row < encoder->height; row++) { + prev = buf; + buf += stride; + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; + quic_one_uncompress_row(encoder, &encoder->channels[0], (one_byte_t *)prev, + (one_byte_t *)buf, encoder->width); + encoder->rows_completed++; + } +} + +#define QUIC_UNCOMPRESS_RGB(prefix, type) \ + encoder->channels[0].correlate_row[-1] = 0; \ + encoder->channels[1].correlate_row[-1] = 0; \ + encoder->channels[2].correlate_row[-1] = 0; \ + quic_rgb##prefix##_uncompress_row0(encoder, (type *)buf, encoder->width); \ + encoder->rows_completed++; \ + for (row = 1; row < encoder->height; row++) { \ + prev = buf; \ + buf += stride; \ + encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \ + encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \ + encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \ + quic_rgb##prefix##_uncompress_row(encoder, (type *)prev, (type *)buf, \ + encoder->width); \ + encoder->rows_completed++; \ + } + +int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride) +{ + Encoder *encoder = (Encoder *)quic; + unsigned int row; + uint8_t *prev; +#ifndef QUIC_RGB + int i; +#endif + + spice_assert(buf); + + switch (encoder->type) { +#ifdef QUIC_RGB + case QUIC_IMAGE_TYPE_RGB32: + case QUIC_IMAGE_TYPE_RGB24: + if (type == QUIC_IMAGE_TYPE_RGB32) { + spice_assert(ABS(stride) >= (int)encoder->width * 4); + QUIC_UNCOMPRESS_RGB(32, rgb32_pixel_t); + break; + } else if (type == QUIC_IMAGE_TYPE_RGB24) { + spice_assert(ABS(stride) >= (int)encoder->width * 3); + QUIC_UNCOMPRESS_RGB(24, rgb24_pixel_t); + break; + } + encoder->usr->warn(encoder->usr, "unsupported output format\n"); + return QUIC_ERROR; + case QUIC_IMAGE_TYPE_RGB16: + if (type == QUIC_IMAGE_TYPE_RGB16) { + spice_assert(ABS(stride) >= (int)encoder->width * 2); + QUIC_UNCOMPRESS_RGB(16, rgb16_pixel_t); + } else if (type == QUIC_IMAGE_TYPE_RGB32) { + spice_assert(ABS(stride) >= (int)encoder->width * 4); + QUIC_UNCOMPRESS_RGB(16_to_32, rgb32_pixel_t); + } else { + encoder->usr->warn(encoder->usr, "unsupported output format\n"); + return QUIC_ERROR; + } + + break; + case QUIC_IMAGE_TYPE_RGBA: + + if (type != QUIC_IMAGE_TYPE_RGBA) { + encoder->usr->warn(encoder->usr, "unsupported output format\n"); + return QUIC_ERROR; + } + spice_assert(ABS(stride) >= (int)encoder->width * 4); + uncompress_rgba(encoder, buf, stride); + break; +#else + case QUIC_IMAGE_TYPE_RGB24: + spice_assert(ABS(stride) >= (int)encoder->width * 3); + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = 0; + quic_three_uncompress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(buf + i), + encoder->width); + } + encoder->rows_completed++; + for (row = 1; row < encoder->height; row++) { + prev = buf; + buf += stride; + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; + quic_three_uncompress_row(encoder, &encoder->channels[i], + (three_bytes_t *)(prev + i), + (three_bytes_t *)(buf + i), + encoder->width); + } + encoder->rows_completed++; + } + break; + case QUIC_IMAGE_TYPE_RGB32: + spice_assert(ABS(stride) >= encoder->width * 4); + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = 0; + quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i), + encoder->width); + } + clear_row((four_bytes_t *)(buf + 3), encoder->width); + encoder->rows_completed++; + for (row = 1; row < encoder->height; row++) { + prev = buf; + buf += stride; + for (i = 0; i < 3; i++) { + encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; + quic_four_uncompress_row(encoder, &encoder->channels[i], + (four_bytes_t *)(prev + i), + (four_bytes_t *)(buf + i), + encoder->width); + } + clear_row((four_bytes_t *)(buf + 3), encoder->width); + encoder->rows_completed++; + } + break; + case QUIC_IMAGE_TYPE_RGBA: + spice_assert(ABS(stride) >= encoder->width * 4); + for (i = 0; i < 4; i++) { + encoder->channels[i].correlate_row[-1] = 0; + quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i), + encoder->width); + } + encoder->rows_completed++; + for (row = 1; row < encoder->height; row++) { + prev = buf; + buf += stride; + for (i = 0; i < 4; i++) { + encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; + quic_four_uncompress_row(encoder, &encoder->channels[i], + (four_bytes_t *)(prev + i), + (four_bytes_t *)(buf + i), + encoder->width); + } + encoder->rows_completed++; + } + break; +#endif + case QUIC_IMAGE_TYPE_GRAY: + + if (type != QUIC_IMAGE_TYPE_GRAY) { + encoder->usr->warn(encoder->usr, "unsupported output format\n"); + return QUIC_ERROR; + } + spice_assert(ABS(stride) >= (int)encoder->width); + uncompress_gray(encoder, buf, stride); + break; + case QUIC_IMAGE_TYPE_INVALID: + default: + encoder->usr->error(encoder->usr, "bad image type\n"); + } + return QUIC_OK; +} + +QuicContext *quic_create(QuicUsrContext *usr) +{ + Encoder *encoder; + + if (!usr || !usr->error || !usr->warn || !usr->info || !usr->malloc || + !usr->free || !usr->more_space || !usr->more_lines) { + return NULL; + } + + if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) { + return NULL; + } + + if (!init_encoder(encoder, usr)) { + usr->free(usr, encoder); + return NULL; + } + return (QuicContext *)encoder; +} + +void quic_destroy(QuicContext *quic) +{ + Encoder *encoder = (Encoder *)quic; + int i; + + if (!quic) { + return; + } + + for (i = 0; i < MAX_CHANNELS; i++) { + destroy_channel(&encoder->channels[i]); + } + encoder->usr->free(encoder->usr, encoder); +} + +SPICE_CONSTRUCTOR_FUNC(quic_global_init) +{ + family_init(&family_8bpc, 8, DEFmaxclen); + family_init(&family_5bpc, 5, DEFmaxclen); +} diff --git a/spice-common/common/quic.h b/spice-common/common/quic.h new file mode 100644 index 0000000..97622b3 --- /dev/null +++ b/spice-common/common/quic.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef __QUIC_H +#define __QUIC_H + +#include +#include "quic_config.h" +#include "macros.h" + +SPICE_BEGIN_DECLS + +typedef enum { + QUIC_IMAGE_TYPE_INVALID, + QUIC_IMAGE_TYPE_GRAY, + QUIC_IMAGE_TYPE_RGB16, + QUIC_IMAGE_TYPE_RGB24, + QUIC_IMAGE_TYPE_RGB32, + QUIC_IMAGE_TYPE_RGBA +} QuicImageType; + +#define QUIC_ERROR -1 +#define QUIC_OK 0 + +typedef void *QuicContext; + +typedef struct QuicUsrContext QuicUsrContext; +struct QuicUsrContext { + SPICE_ATTR_PRINTF(2, 3) void (*error)(QuicUsrContext *usr, const char *fmt, ...); + SPICE_ATTR_PRINTF(2, 3) void (*warn)(QuicUsrContext *usr, const char *fmt, ...); + SPICE_ATTR_PRINTF(2, 3) void (*info)(QuicUsrContext *usr, const char *fmt, ...); + void *(*malloc)(QuicUsrContext *usr, int size); + void (*free)(QuicUsrContext *usr, void *ptr); + int (*more_space)(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed); + int (*more_lines)(QuicUsrContext *usr, uint8_t **lines); // on return the last line of previous + // lines bunch must still be valid +}; + +int quic_encode(QuicContext *quic, QuicImageType type, int width, int height, + uint8_t *lines, unsigned int num_lines, int stride, + uint32_t *io_ptr, unsigned int num_io_words); + +int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words, + QuicImageType *type, int *width, int *height); +int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride); + + +QuicContext *quic_create(QuicUsrContext *usr); +void quic_destroy(QuicContext *quic); + +static inline SPICE_GNUC_DEPRECATED void quic_init(void) {} + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/quic_config.h b/spice-common/common/quic_config.h new file mode 100644 index 0000000..fe89014 --- /dev/null +++ b/spice-common/common/quic_config.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef __QUIC_CONFIG_H +#define __QUIC_CONFIG_H + +#include +#include + +SPICE_BEGIN_DECLS + +#ifdef __GNUC__ +#include +#define MEMCLEAR(ptr, size) memset(ptr, 0, size) +#else +#ifdef QXLDD +#include +#include "os_dep.h" +#define MEMCLEAR(ptr, size) RtlZeroMemory(ptr, size) +#else +#include +#include +#define MEMCLEAR(ptr, size) memset(ptr, 0, size) +#endif // QXLDD +#endif //__GNUC__ + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/quic_family_tmpl.c b/spice-common/common/quic_family_tmpl.c new file mode 100644 index 0000000..9a434e0 --- /dev/null +++ b/spice-common/common/quic_family_tmpl.c @@ -0,0 +1,115 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef QUIC_FAMILY_8BPC +#undef QUIC_FAMILY_8BPC +#define FNAME(name) name##_8bpc +#define VNAME(name) name##_8bpc +#define BPC 8 +#endif + + +#ifdef QUIC_FAMILY_5BPC +#undef QUIC_FAMILY_5BPC +#define FNAME(name) name##_5bpc +#define VNAME(name) name##_5bpc +#define BPC 5 +#endif + +static inline unsigned int FNAME(golomb_code)(const BYTE n, const unsigned int l) +{ + return VNAME(family).golomb_code[n][l]; +} + +static inline unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l) +{ + return VNAME(family).golomb_code_len[n][l]; +} + +static void FNAME(golomb_coding)(const BYTE n, const unsigned int l, unsigned int * const codeword, + unsigned int * const codewordlen) +{ + *codeword = FNAME(golomb_code)(n, l); + *codewordlen = FNAME(golomb_code_len)(n, l); +} + +static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits, + unsigned int * const codewordlen) +{ + if (bits > VNAME(family).notGRprefixmask[l]) { /*GR*/ + const unsigned int zeroprefix = cnt_l_zeroes(bits); /* leading zeroes in codeword */ + const unsigned int cwlen = zeroprefix + 1 + l; /* codeword length */ + (*codewordlen) = cwlen; + return (zeroprefix << l) | ((bits >> (32 - cwlen)) & bppmask[l]); + } else { /* not-GR */ + const unsigned int cwlen = VNAME(family).notGRcwlen[l]; + (*codewordlen) = cwlen; + return VNAME(family).nGRcodewords[l] + ((bits) >> (32 - cwlen) & + bppmask[VNAME(family).notGRsuffixlen[l]]); + } +} + +/* update the bucket using just encoded curval */ +static void FNAME(update_model)(CommonState *state, s_bucket * const bucket, + const BYTE curval) +{ + spice_static_assert(BPC >= 1); + spice_return_if_fail (bucket != NULL); + + const unsigned int bpp = BPC; + COUNTER * const pcounters = bucket->pcounters; + unsigned int i; + unsigned int bestcode; + unsigned int bestcodelen; + + /* update counters, find minimum */ + + bestcode = bpp - 1; + bestcodelen = (pcounters[bestcode] += FNAME(golomb_code_len)(curval, bestcode)); + + for (i = bpp - 2; i < bpp; i--) { /* NOTE: expression i=0 */ + const unsigned int ithcodelen = (pcounters[i] += FNAME(golomb_code_len)(curval, i)); + + if (ithcodelen < bestcodelen) { + bestcode = i; + bestcodelen = ithcodelen; + } + } + + bucket->bestcode = bestcode; /* store the found minimum */ + + if (bestcodelen > state->wm_trigger) { /* halving counters? */ + for (i = 0; i < bpp; i++) { + pcounters[i] >>= 1; + } + } +} + +static s_bucket *FNAME(find_bucket)(Channel *channel, const unsigned int val) +{ + spice_assert(val < (0x1U << BPC)); + + return channel->_buckets_ptrs[val]; +} + +#undef FNAME +#undef VNAME +#undef BPC diff --git a/spice-common/common/quic_rgb_tmpl.c b/spice-common/common/quic_rgb_tmpl.c new file mode 100644 index 0000000..f807a0c --- /dev/null +++ b/spice-common/common/quic_rgb_tmpl.c @@ -0,0 +1,765 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef QUIC_RGB32 +#undef QUIC_RGB32 +#define PIXEL rgb32_pixel_t +#define FNAME(name) quic_rgb32_##name +#define golomb_coding golomb_coding_8bpc +#define golomb_decoding golomb_decoding_8bpc +#define update_model update_model_8bpc +#define find_bucket find_bucket_8bpc +#define family family_8bpc +#define BPC 8 +#define BPC_MASK 0xffU +#define COMPRESS_IMP +#define SET_r(pix, val) ((pix)->r = val) +#define GET_r(pix) ((pix)->r) +#define SET_g(pix, val) ((pix)->g = val) +#define GET_g(pix) ((pix)->g) +#define SET_b(pix, val) ((pix)->b = val) +#define GET_b(pix) ((pix)->b) +#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0) +#endif + +#ifdef QUIC_RGB24 +#undef QUIC_RGB24 +#define PIXEL rgb24_pixel_t +#define FNAME(name) quic_rgb24_##name +#define golomb_coding golomb_coding_8bpc +#define golomb_decoding golomb_decoding_8bpc +#define update_model update_model_8bpc +#define find_bucket find_bucket_8bpc +#define family family_8bpc +#define BPC 8 +#define BPC_MASK 0xffU +#define COMPRESS_IMP +#define SET_r(pix, val) ((pix)->r = val) +#define GET_r(pix) ((pix)->r) +#define SET_g(pix, val) ((pix)->g = val) +#define GET_g(pix) ((pix)->g) +#define SET_b(pix, val) ((pix)->b = val) +#define GET_b(pix) ((pix)->b) +#define UNCOMPRESS_PIX_START(pix) +#endif + +#ifdef QUIC_RGB16 +#undef QUIC_RGB16 +#define PIXEL rgb16_pixel_t +#define FNAME(name) quic_rgb16_##name +#define golomb_coding golomb_coding_5bpc +#define golomb_decoding golomb_decoding_5bpc +#define update_model update_model_5bpc +#define find_bucket find_bucket_5bpc +#define family family_5bpc +#define BPC 5 +#define BPC_MASK 0x1fU +#define COMPRESS_IMP +#define SET_r(pix, val) (*(pix) = (*(pix) & ~(0x1f << 10)) | ((val) << 10)) +#define GET_r(pix) ((*(pix) >> 10) & 0x1f) +#define SET_g(pix, val) (*(pix) = (*(pix) & ~(0x1f << 5)) | ((val) << 5)) +#define GET_g(pix) ((*(pix) >> 5) & 0x1f) +#define SET_b(pix, val) (*(pix) = (*(pix) & ~0x1f) | (val)) +#define GET_b(pix) (*(pix) & 0x1f) +#define UNCOMPRESS_PIX_START(pix) (*(pix) = 0) +#endif + +#ifdef QUIC_RGB16_TO_32 +#undef QUIC_RGB16_TO_32 +#define PIXEL rgb32_pixel_t +#define FNAME(name) quic_rgb16_to_32_##name +#define golomb_coding golomb_coding_5bpc +#define golomb_decoding golomb_decoding_5bpc +#define update_model update_model_5bpc +#define find_bucket find_bucket_5bpc +#define family family_5bpc +#define BPC 5 +#define BPC_MASK 0x1fU + +#define SET_r(pix, val) ((pix)->r = ((val) << 3) | (((val) & 0x1f) >> 2)) +#define GET_r(pix) ((pix)->r >> 3) +#define SET_g(pix, val) ((pix)->g = ((val) << 3) | (((val) & 0x1f) >> 2)) +#define GET_g(pix) ((pix)->g >> 3) +#define SET_b(pix, val) ((pix)->b = ((val) << 3) | (((val) & 0x1f) >> 2)) +#define GET_b(pix) ((pix)->b >> 3) +#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0) +#endif + +#define SAME_PIXEL(p1, p2) \ + (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \ + GET_b(p1) == GET_b(p2)) + + +#define _PIXEL_A(channel, curr) ((unsigned int)GET_##channel((curr) - 1)) +#define _PIXEL_B(channel, prev) ((unsigned int)GET_##channel(prev)) +#define _PIXEL_C(channel, prev) ((unsigned int)GET_##channel((prev) - 1)) + +/* a */ + +#define DECORELATE_0(channel, curr, bpc_mask)\ + family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)_PIXEL_A(channel, curr)) & bpc_mask] + +#define CORELATE_0(channel, curr, correlate, bpc_mask)\ + ((family.xlatL2U[correlate] + _PIXEL_A(channel, curr)) & bpc_mask) + +#ifdef PRED_1 + +/* (a+b)/2 */ +#define DECORELATE(channel, prev, curr, bpc_mask, r) \ + r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)((_PIXEL_A(channel, curr) + \ + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask] + +#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) \ + SET_##channel(r, ((family.xlatL2U[correlate] + \ + (int)((_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask)) +#endif + +#ifdef PRED_2 + +/* .75a+.75b-.5c */ +#define DECORELATE(channel, prev, curr, bpc_mask, r) { \ + int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \ + (int)(_PIXEL_C(channel, prev) << 1)) >> 2; \ + if (p < 0) { \ + p = 0; \ + } else if ((unsigned)p > bpc_mask) { \ + p = bpc_mask; \ + } \ + r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - p) & bpc_mask]; \ +} + +#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) { \ + const int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \ + (int)(_PIXEL_C(channel, prev) << 1) ) >> 2; \ + const unsigned int s = family.xlatL2U[correlate]; \ + if (!(p & ~bpc_mask)) { \ + SET_##channel(r, (s + (unsigned)p) & bpc_mask); \ + } else if (p < 0) { \ + SET_##channel(r, s); \ + } else { \ + SET_##channel(r, (s + bpc_mask) & bpc_mask); \ + } \ +} + +#endif + + +#define COMPRESS_ONE_ROW0_0(channel) \ + correlate_row_##channel[0] = family.xlatU2L[GET_##channel(cur_row)]; \ + golomb_coding(correlate_row_##channel[0], find_bucket(channel_##channel, \ + correlate_row_##channel[-1])->bestcode, \ + &codeword, &codewordlen); \ + encode(encoder, codeword, codewordlen); + +#define COMPRESS_ONE_ROW0(channel, index) \ + correlate_row_##channel[index] = DECORELATE_0(channel, &cur_row[index], bpc_mask); \ + golomb_coding(correlate_row_##channel[index], find_bucket(channel_##channel, \ + correlate_row_##channel[index -1])->bestcode, \ + &codeword, &codewordlen); \ + encode(encoder, codeword, codewordlen); + +#define UPDATE_MODEL(index) \ + update_model(&encoder->rgb_state, find_bucket(channel_r, correlate_row_r[index - 1]), \ + correlate_row_r[index]); \ + update_model(&encoder->rgb_state, find_bucket(channel_g, correlate_row_g[index - 1]), \ + correlate_row_g[index]); \ + update_model(&encoder->rgb_state, find_bucket(channel_b, correlate_row_b[index - 1]), \ + correlate_row_b[index]); + + +#ifdef RLE_PRED_1 +#define RLE_PRED_1_IMP \ +if (SAME_PIXEL(&cur_row[i - 1], &prev_row[i])) { \ + if (run_index != i && SAME_PIXEL(&prev_row[i - 1], &prev_row[i]) && \ + i + 1 < end && SAME_PIXEL(&prev_row[i], &prev_row[i + 1])) { \ + goto do_run; \ + } \ +} +#else +#define RLE_PRED_1_IMP +#endif + +#ifdef RLE_PRED_2 +#define RLE_PRED_2_IMP \ +if (SAME_PIXEL(&prev_row[i - 1], &prev_row[i])) { \ + if (run_index != i && i > 2 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2])) { \ + goto do_run; \ + } \ +} +#else +#define RLE_PRED_2_IMP +#endif + +#ifdef RLE_PRED_3 +#define RLE_PRED_3_IMP \ +if (i > 1 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2]) && i != run_index) { \ + goto do_run; \ +} +#else +#define RLE_PRED_3_IMP +#endif + +#ifdef COMPRESS_IMP + +static void FNAME(compress_row0_seg)(Encoder *encoder, int i, + const PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + Channel * const channel_r = encoder->channels; + Channel * const channel_g = channel_r + 1; + Channel * const channel_b = channel_g + 1; + + BYTE * const correlate_row_r = channel_r->correlate_row; + BYTE * const correlate_row_g = channel_g->correlate_row; + BYTE * const correlate_row_b = channel_b->correlate_row; + int stopidx; + + spice_assert(end - i > 0); + + if (!i) { + unsigned int codeword, codewordlen; + + COMPRESS_ONE_ROW0_0(r); + COMPRESS_ONE_ROW0_0(g); + COMPRESS_ONE_ROW0_0(b); + + if (encoder->rgb_state.waitcnt) { + encoder->rgb_state.waitcnt--; + } else { + encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + UPDATE_MODEL(0); + } + stopidx = ++i + encoder->rgb_state.waitcnt; + } else { + stopidx = i + encoder->rgb_state.waitcnt; + } + + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codeword, codewordlen; + COMPRESS_ONE_ROW0(r, i); + COMPRESS_ONE_ROW0(g, i); + COMPRESS_ONE_ROW0(b, i); + } + + UPDATE_MODEL(stopidx); + stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codeword, codewordlen; + + COMPRESS_ONE_ROW0(r, i); + COMPRESS_ONE_ROW0(g, i); + COMPRESS_ONE_ROW0(b, i); + } + encoder->rgb_state.waitcnt = stopidx - end; +} + +static void FNAME(compress_row0)(Encoder *encoder, const PIXEL *cur_row, + unsigned int width) +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + int pos = 0; + + while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { + if (encoder->rgb_state.wmileft) { + FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + encoder->rgb_state.wmileft, + bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); + width -= encoder->rgb_state.wmileft; + pos += encoder->rgb_state.wmileft; + } + + encoder->rgb_state.wmidx++; + set_wm_trigger(&encoder->rgb_state); + encoder->rgb_state.wmileft = wminext; + } + + if (width) { + FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + width, + bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); + if (wmimax > (int)encoder->rgb_state.wmidx) { + encoder->rgb_state.wmileft -= width; + } + } + + spice_assert((int)encoder->rgb_state.wmidx <= wmimax); + spice_assert(encoder->rgb_state.wmidx <= 32); + spice_assert(wminext > 0); +} + +#define COMPRESS_ONE_0(channel) \ + correlate_row_##channel[0] = family.xlatU2L[(unsigned)((int)GET_##channel(cur_row) - \ + (int)GET_##channel(prev_row) ) & bpc_mask]; \ + golomb_coding(correlate_row_##channel[0], \ + find_bucket(channel_##channel, correlate_row_##channel[-1])->bestcode, \ + &codeword, &codewordlen); \ + encode(encoder, codeword, codewordlen); + +#define COMPRESS_ONE(channel, index) \ + DECORELATE(channel, &prev_row[index], &cur_row[index],bpc_mask, \ + correlate_row_##channel[index]); \ + golomb_coding(correlate_row_##channel[index], \ + find_bucket(channel_##channel, correlate_row_##channel[index - 1])->bestcode, \ + &codeword, &codewordlen); \ + encode(encoder, codeword, codewordlen); + +static void FNAME(compress_row_seg)(Encoder *encoder, int i, + const PIXEL * const prev_row, + const PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + Channel * const channel_r = encoder->channels; + Channel * const channel_g = channel_r + 1; + Channel * const channel_b = channel_g + 1; + + BYTE * const correlate_row_r = channel_r->correlate_row; + BYTE * const correlate_row_g = channel_g->correlate_row; + BYTE * const correlate_row_b = channel_b->correlate_row; + int stopidx; +#ifdef RLE + int run_index = 0; + int run_size; +#endif + + spice_assert(end - i > 0); + + if (!i) { + unsigned int codeword, codewordlen; + + COMPRESS_ONE_0(r); + COMPRESS_ONE_0(g); + COMPRESS_ONE_0(b); + + if (encoder->rgb_state.waitcnt) { + encoder->rgb_state.waitcnt--; + } else { + encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + UPDATE_MODEL(0); + } + stopidx = ++i + encoder->rgb_state.waitcnt; + } else { + stopidx = i + encoder->rgb_state.waitcnt; + } + for (;;) { + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codeword, codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + COMPRESS_ONE(r, i); + COMPRESS_ONE(g, i); + COMPRESS_ONE(b, i); + } + + UPDATE_MODEL(stopidx); + stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codeword, codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + COMPRESS_ONE(r, i); + COMPRESS_ONE(g, i); + COMPRESS_ONE(b, i); + } + encoder->rgb_state.waitcnt = stopidx - end; + + return; + +#ifdef RLE +do_run: + run_index = i; + encoder->rgb_state.waitcnt = stopidx - i; + run_size = 0; + + while (SAME_PIXEL(&cur_row[i], &cur_row[i - 1])) { + run_size++; + if (++i == end) { + encode_run(encoder, run_size); + return; + } + } + encode_run(encoder, run_size); + stopidx = i + encoder->rgb_state.waitcnt; +#endif + } +} + +static void FNAME(compress_row)(Encoder *encoder, + const PIXEL * const prev_row, + const PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + unsigned int pos = 0; + + while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { + if (encoder->rgb_state.wmileft) { + FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, + pos + encoder->rgb_state.wmileft, + bppmask[encoder->rgb_state.wmidx], + bpc, bpc_mask); + width -= encoder->rgb_state.wmileft; + pos += encoder->rgb_state.wmileft; + } + + encoder->rgb_state.wmidx++; + set_wm_trigger(&encoder->rgb_state); + encoder->rgb_state.wmileft = wminext; + } + + if (width) { + FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, pos + width, + bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); + if (wmimax > (int)encoder->rgb_state.wmidx) { + encoder->rgb_state.wmileft -= width; + } + } + + spice_assert((int)encoder->rgb_state.wmidx <= wmimax); + spice_assert(encoder->rgb_state.wmidx <= 32); + spice_assert(wminext > 0); +} + +#endif + +#define UNCOMPRESS_ONE_ROW0_0(channel) \ + correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ + correlate_row_##channel[-1])->bestcode, \ + encoder->io_word, &codewordlen); \ + SET_##channel(&cur_row[0], (BYTE)family.xlatL2U[correlate_row_##channel[0]]); \ + decode_eatbits(encoder, codewordlen); + +#define UNCOMPRESS_ONE_ROW0(channel) \ + correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ + correlate_row_##channel[i - 1])->bestcode, \ + encoder->io_word, \ + &codewordlen); \ + SET_##channel(&cur_row[i], CORELATE_0(channel, &cur_row[i], correlate_row_##channel[i], \ + bpc_mask)); \ + decode_eatbits(encoder, codewordlen); + +static void FNAME(uncompress_row0_seg)(Encoder *encoder, int i, + PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + Channel * const channel_r = encoder->channels; + Channel * const channel_g = channel_r + 1; + Channel * const channel_b = channel_g + 1; + + BYTE * const correlate_row_r = channel_r->correlate_row; + BYTE * const correlate_row_g = channel_g->correlate_row; + BYTE * const correlate_row_b = channel_b->correlate_row; + int stopidx; + + spice_assert(end - i > 0); + + if (!i) { + unsigned int codewordlen; + + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE_ROW0_0(r); + UNCOMPRESS_ONE_ROW0_0(g); + UNCOMPRESS_ONE_ROW0_0(b); + + if (encoder->rgb_state.waitcnt) { + --encoder->rgb_state.waitcnt; + } else { + encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + UPDATE_MODEL(0); + } + stopidx = ++i + encoder->rgb_state.waitcnt; + } else { + stopidx = i + encoder->rgb_state.waitcnt; + } + + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codewordlen; + + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE_ROW0(r); + UNCOMPRESS_ONE_ROW0(g); + UNCOMPRESS_ONE_ROW0(b); + } + UPDATE_MODEL(stopidx); + stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codewordlen; + + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE_ROW0(r); + UNCOMPRESS_ONE_ROW0(g); + UNCOMPRESS_ONE_ROW0(b); + } + encoder->rgb_state.waitcnt = stopidx - end; +} + +static void FNAME(uncompress_row0)(Encoder *encoder, + PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + unsigned int pos = 0; + + while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { + if (encoder->rgb_state.wmileft) { + FNAME(uncompress_row0_seg)(encoder, pos, cur_row, + pos + encoder->rgb_state.wmileft, + bppmask[encoder->rgb_state.wmidx], + bpc, bpc_mask); + pos += encoder->rgb_state.wmileft; + width -= encoder->rgb_state.wmileft; + } + + encoder->rgb_state.wmidx++; + set_wm_trigger(&encoder->rgb_state); + encoder->rgb_state.wmileft = wminext; + } + + if (width) { + FNAME(uncompress_row0_seg)(encoder, pos, cur_row, pos + width, + bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); + if (wmimax > (int)encoder->rgb_state.wmidx) { + encoder->rgb_state.wmileft -= width; + } + } + + spice_assert((int)encoder->rgb_state.wmidx <= wmimax); + spice_assert(encoder->rgb_state.wmidx <= 32); + spice_assert(wminext > 0); +} + +#define UNCOMPRESS_ONE_0(channel) \ + correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ + correlate_row_##channel[-1])->bestcode, \ + encoder->io_word, &codewordlen); \ + SET_##channel(&cur_row[0], (family.xlatL2U[correlate_row_##channel[0]] + \ + GET_##channel(prev_row)) & bpc_mask); \ + decode_eatbits(encoder, codewordlen); + +#define UNCOMPRESS_ONE(channel) \ + correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ + correlate_row_##channel[i - 1])->bestcode, \ + encoder->io_word, \ + &codewordlen); \ + CORELATE(channel, &prev_row[i], &cur_row[i], correlate_row_##channel[i], bpc_mask, \ + &cur_row[i]); \ + decode_eatbits(encoder, codewordlen); + +static void FNAME(uncompress_row_seg)(Encoder *encoder, + const PIXEL * const prev_row, + PIXEL * const cur_row, + int i, + const int end, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + Channel * const channel_r = encoder->channels; + Channel * const channel_g = channel_r + 1; + Channel * const channel_b = channel_g + 1; + + BYTE * const correlate_row_r = channel_r->correlate_row; + BYTE * const correlate_row_g = channel_g->correlate_row; + BYTE * const correlate_row_b = channel_b->correlate_row; + const unsigned int waitmask = bppmask[encoder->rgb_state.wmidx]; + int stopidx; +#ifdef RLE + int run_index = 0; + int run_end; +#endif + + spice_assert(end - i > 0); + + if (!i) { + unsigned int codewordlen; + + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE_0(r); + UNCOMPRESS_ONE_0(g); + UNCOMPRESS_ONE_0(b); + + if (encoder->rgb_state.waitcnt) { + --encoder->rgb_state.waitcnt; + } else { + encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + UPDATE_MODEL(0); + } + stopidx = ++i + encoder->rgb_state.waitcnt; + } else { + stopidx = i + encoder->rgb_state.waitcnt; + } + for (;;) { + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE(r); + UNCOMPRESS_ONE(g); + UNCOMPRESS_ONE(b); + } + + UPDATE_MODEL(stopidx); + + stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + UNCOMPRESS_PIX_START(&cur_row[i]); + UNCOMPRESS_ONE(r); + UNCOMPRESS_ONE(g); + UNCOMPRESS_ONE(b); + } + + encoder->rgb_state.waitcnt = stopidx - end; + + return; + +#ifdef RLE +do_run: + encoder->rgb_state.waitcnt = stopidx - i; + run_index = i; + run_end = i + decode_run(encoder); + + for (; i < run_end; i++) { + UNCOMPRESS_PIX_START(&cur_row[i]); + SET_r(&cur_row[i], GET_r(&cur_row[i - 1])); + SET_g(&cur_row[i], GET_g(&cur_row[i - 1])); + SET_b(&cur_row[i], GET_b(&cur_row[i - 1])); + } + + if (i == end) { + return; + } + + stopidx = i + encoder->rgb_state.waitcnt; +#endif + } +} + +static void FNAME(uncompress_row)(Encoder *encoder, + const PIXEL * const prev_row, + PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + unsigned int pos = 0; + + while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { + if (encoder->rgb_state.wmileft) { + FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos, + pos + encoder->rgb_state.wmileft, bpc, bpc_mask); + pos += encoder->rgb_state.wmileft; + width -= encoder->rgb_state.wmileft; + } + + encoder->rgb_state.wmidx++; + set_wm_trigger(&encoder->rgb_state); + encoder->rgb_state.wmileft = wminext; + } + + if (width) { + FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos, + pos + width, bpc, bpc_mask); + if (wmimax > (int)encoder->rgb_state.wmidx) { + encoder->rgb_state.wmileft -= width; + } + } + + spice_assert((int)encoder->rgb_state.wmidx <= wmimax); + spice_assert(encoder->rgb_state.wmidx <= 32); + spice_assert(wminext > 0); +} + +#undef PIXEL +#undef FNAME +#undef _PIXEL_A +#undef _PIXEL_B +#undef _PIXEL_C +#undef SAME_PIXEL +#undef RLE_PRED_1_IMP +#undef RLE_PRED_2_IMP +#undef RLE_PRED_3_IMP +#undef UPDATE_MODEL +#undef DECORELATE_0 +#undef DECORELATE +#undef COMPRESS_ONE_ROW0_0 +#undef COMPRESS_ONE_ROW0 +#undef COMPRESS_ONE_0 +#undef COMPRESS_ONE +#undef CORELATE_0 +#undef CORELATE +#undef UNCOMPRESS_ONE_ROW0_0 +#undef UNCOMPRESS_ONE_ROW0 +#undef UNCOMPRESS_ONE_0 +#undef UNCOMPRESS_ONE +#undef golomb_coding +#undef golomb_decoding +#undef update_model +#undef find_bucket +#undef family +#undef BPC +#undef BPC_MASK +#undef COMPRESS_IMP +#undef SET_r +#undef GET_r +#undef SET_g +#undef GET_g +#undef SET_b +#undef GET_b +#undef UNCOMPRESS_PIX_START diff --git a/spice-common/common/quic_tmpl.c b/spice-common/common/quic_tmpl.c new file mode 100644 index 0000000..e839346 --- /dev/null +++ b/spice-common/common/quic_tmpl.c @@ -0,0 +1,635 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef ONE_BYTE +#undef ONE_BYTE +#define FNAME(name) quic_one_##name +#define PIXEL one_byte_t +#endif + +#ifdef THREE_BYTE +#undef THREE_BYTE +#define FNAME(name) quic_three_##name +#define PIXEL three_bytes_t +#endif + +#ifdef FOUR_BYTE +#undef FOUR_BYTE +#define FNAME(name) quic_four_##name +#define PIXEL four_bytes_t +#endif + +#define golomb_coding golomb_coding_8bpc +#define golomb_decoding golomb_decoding_8bpc +#define update_model update_model_8bpc +#define find_bucket find_bucket_8bpc +#define family family_8bpc + +#define BPC 8 +#define BPC_MASK 0xffU + +#define _PIXEL_A ((unsigned int)curr[-1].a) +#define _PIXEL_B ((unsigned int)prev[0].a) +#define _PIXEL_C ((unsigned int)prev[-1].a) + +#ifdef RLE_PRED_1 +#define RLE_PRED_1_IMP \ +if (cur_row[i - 1].a == prev_row[i].a) { \ + if (run_index != i && prev_row[i - 1].a == prev_row[i].a && \ + i + 1 < end && prev_row[i].a == prev_row[i + 1].a) { \ + goto do_run; \ + } \ +} +#else +#define RLE_PRED_1_IMP +#endif + +#ifdef RLE_PRED_2 +#define RLE_PRED_2_IMP \ +if (prev_row[i - 1].a == prev_row[i].a) { \ + if (run_index != i && i > 2 && cur_row[i - 1].a == cur_row[i - 2].a) { \ + goto do_run; \ + } \ +} +#else +#define RLE_PRED_2_IMP +#endif + +#ifdef RLE_PRED_3 +#define RLE_PRED_3_IMP \ +if (i > 1 && cur_row[i - 1].a == cur_row[i - 2].a && i != run_index) { \ + goto do_run; \ +} +#else +#define RLE_PRED_3_IMP +#endif + +/* a */ +static inline BYTE FNAME(decorelate_0)(const PIXEL * const curr, const unsigned int bpc_mask) +{ + return family.xlatU2L[(unsigned)((int)curr[0].a - (int)_PIXEL_A) & bpc_mask]; +} + +static inline void FNAME(corelate_0)(PIXEL *curr, const BYTE corelate, + const unsigned int bpc_mask) +{ + curr->a = (family.xlatL2U[corelate] + _PIXEL_A) & bpc_mask; +} + +#ifdef PRED_1 + +/* (a+b)/2 */ +static inline BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr, + const unsigned int bpc_mask) +{ + return family.xlatU2L[(unsigned)((int)curr->a - (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask]; +} + + +static inline void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate, + const unsigned int bpc_mask) +{ + curr->a = (family.xlatL2U[corelate] + (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask; +} + +#endif + +#ifdef PRED_2 + +/* .75a+.75b-.5c */ +static inline BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr, + const unsigned int bpc_mask) +{ + int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2; + + if (p < 0) { + p = 0; + } else if ((unsigned)p > bpc_mask) { + p = bpc_mask; + } + + { + return family.xlatU2L[(unsigned)((int)curr->a - p) & bpc_mask]; + } +} + +static inline void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate, + const unsigned int bpc_mask) +{ + const int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2; + const unsigned int s = family.xlatL2U[corelate]; + + if (!(p & ~bpc_mask)) { + curr->a = (s + (unsigned)p) & bpc_mask; + } else if (p < 0) { + curr->a = s; + } else { + curr->a = (s + bpc_mask) & bpc_mask; + } +} + +#endif + +static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i, + const PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + BYTE * const decorelate_drow = channel->correlate_row; + int stopidx; + + spice_assert(end - i > 0); + + if (i == 0) { + unsigned int codeword, codewordlen; + + decorelate_drow[0] = family.xlatU2L[cur_row->a]; + golomb_coding(decorelate_drow[0], find_bucket(channel, decorelate_drow[-1])->bestcode, + &codeword, &codewordlen); + encode(encoder, codeword, codewordlen); + + if (channel->state.waitcnt) { + channel->state.waitcnt--; + } else { + channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); + update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]), + decorelate_drow[i]); + } + stopidx = ++i + channel->state.waitcnt; + } else { + stopidx = i + channel->state.waitcnt; + } + + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codeword, codewordlen; + decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask); + golomb_coding(decorelate_drow[i], + find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword, + &codewordlen); + encode(encoder, codeword, codewordlen); + } + + update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]), + decorelate_drow[stopidx]); + stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codeword, codewordlen; + decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask); + golomb_coding(decorelate_drow[i], find_bucket(channel, decorelate_drow[i - 1])->bestcode, + &codeword, &codewordlen); + encode(encoder, codeword, codewordlen); + } + channel->state.waitcnt = stopidx - end; +} + +static void FNAME(compress_row0)(Encoder *encoder, Channel *channel, const PIXEL *cur_row, + unsigned int width) +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + int pos = 0; + + while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { + if (channel->state.wmileft) { + FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + channel->state.wmileft, + bppmask[channel->state.wmidx], bpc, bpc_mask); + width -= channel->state.wmileft; + pos += channel->state.wmileft; + } + + channel->state.wmidx++; + set_wm_trigger(&channel->state); + channel->state.wmileft = wminext; + } + + if (width) { + FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + width, + bppmask[channel->state.wmidx], bpc, bpc_mask); + if (wmimax > (int)channel->state.wmidx) { + channel->state.wmileft -= width; + } + } + + spice_assert((int)channel->state.wmidx <= wmimax); + spice_assert(channel->state.wmidx <= 32); + spice_assert(wminext > 0); +} + +static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i, + const PIXEL * const prev_row, + const PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + BYTE * const decorelate_drow = channel->correlate_row; + int stopidx; +#ifdef RLE + int run_index = 0; + int run_size; +#endif + + spice_assert(end - i > 0); + + if (!i) { + unsigned int codeword, codewordlen; + + decorelate_drow[0] = family.xlatU2L[(unsigned)((int)cur_row->a - + (int)prev_row->a) & bpc_mask]; + + golomb_coding(decorelate_drow[0], + find_bucket(channel, decorelate_drow[-1])->bestcode, + &codeword, + &codewordlen); + encode(encoder, codeword, codewordlen); + + if (channel->state.waitcnt) { + channel->state.waitcnt--; + } else { + channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); + update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]), + decorelate_drow[0]); + } + stopidx = ++i + channel->state.waitcnt; + } else { + stopidx = i + channel->state.waitcnt; + } + for (;;) { + while (stopidx < end) { + for (; i <= stopidx; i++) { + unsigned int codeword, codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask); + golomb_coding(decorelate_drow[i], + find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword, + &codewordlen); + encode(encoder, codeword, codewordlen); + } + + update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]), + decorelate_drow[stopidx]); + stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codeword, codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask); + golomb_coding(decorelate_drow[i], find_bucket(channel, + decorelate_drow[i - 1])->bestcode, + &codeword, &codewordlen); + encode(encoder, codeword, codewordlen); + } + channel->state.waitcnt = stopidx - end; + + return; + +#ifdef RLE +do_run: + run_index = i; + channel->state.waitcnt = stopidx - i; + run_size = 0; + + while (cur_row[i].a == cur_row[i - 1].a) { + run_size++; + if (++i == end) { +#ifdef RLE_STAT + encode_channel_run(encoder, channel, run_size); +#else + encode_run(encoder, run_size); +#endif + return; + } + } +#ifdef RLE_STAT + encode_channel_run(encoder, channel, run_size); +#else + encode_run(encoder, run_size); +#endif + stopidx = i + channel->state.waitcnt; +#endif + } +} + +static void FNAME(compress_row)(Encoder *encoder, Channel *channel, + const PIXEL * const prev_row, + const PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + unsigned int pos = 0; + + while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { + if (channel->state.wmileft) { + FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, + pos + channel->state.wmileft, bppmask[channel->state.wmidx], + bpc, bpc_mask); + width -= channel->state.wmileft; + pos += channel->state.wmileft; + } + + channel->state.wmidx++; + set_wm_trigger(&channel->state); + channel->state.wmileft = wminext; + } + + if (width) { + FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, pos + width, + bppmask[channel->state.wmidx], bpc, bpc_mask); + if (wmimax > (int)channel->state.wmidx) { + channel->state.wmileft -= width; + } + } + + spice_assert((int)channel->state.wmidx <= wmimax); + spice_assert(channel->state.wmidx <= 32); + spice_assert(wminext > 0); +} + +static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i, + BYTE * const correlate_row, + PIXEL * const cur_row, + const int end, + const unsigned int waitmask, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + int stopidx; + + spice_assert(end - i > 0); + + if (i == 0) { + unsigned int codewordlen; + + correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, + correlate_row[-1])->bestcode, + encoder->io_word, &codewordlen); + cur_row[0].a = (BYTE)family.xlatL2U[correlate_row[0]]; + decode_eatbits(encoder, codewordlen); + + if (channel->state.waitcnt) { + --channel->state.waitcnt; + } else { + channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); + update_model(&channel->state, find_bucket(channel, correlate_row[-1]), + correlate_row[0]); + } + stopidx = ++i + channel->state.waitcnt; + } else { + stopidx = i + channel->state.waitcnt; + } + + while (stopidx < end) { + struct s_bucket * pbucket = NULL; + + for (; i <= stopidx; i++) { + unsigned int codewordlen; + + pbucket = find_bucket(channel, correlate_row[i - 1]); + correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word, + &codewordlen); + FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask); + decode_eatbits(encoder, codewordlen); + } + + update_model(&channel->state, pbucket, correlate_row[stopidx]); + + stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codewordlen; + + correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel, + correlate_row[i - 1])->bestcode, + encoder->io_word, &codewordlen); + FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask); + decode_eatbits(encoder, codewordlen); + } + channel->state.waitcnt = stopidx - end; +} + +static void FNAME(uncompress_row0)(Encoder *encoder, Channel *channel, + PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + BYTE * const correlate_row = channel->correlate_row; + unsigned int pos = 0; + + while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { + if (channel->state.wmileft) { + FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, + pos + channel->state.wmileft, bppmask[channel->state.wmidx], + bpc, bpc_mask); + pos += channel->state.wmileft; + width -= channel->state.wmileft; + } + + channel->state.wmidx++; + set_wm_trigger(&channel->state); + channel->state.wmileft = wminext; + } + + if (width) { + FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, pos + width, + bppmask[channel->state.wmidx], bpc, bpc_mask); + if (wmimax > (int)channel->state.wmidx) { + channel->state.wmileft -= width; + } + } + + spice_assert((int)channel->state.wmidx <= wmimax); + spice_assert(channel->state.wmidx <= 32); + spice_assert(wminext > 0); +} + +static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel, + BYTE *correlate_row, + const PIXEL * const prev_row, + PIXEL * const cur_row, + int i, + const int end, + SPICE_GNUC_UNUSED const unsigned int bpc, + const unsigned int bpc_mask) +{ + const unsigned int waitmask = bppmask[channel->state.wmidx]; + int stopidx; +#ifdef RLE + int run_index = 0; + int run_end; +#endif + + spice_assert(end - i > 0); + + if (i == 0) { + unsigned int codewordlen; + + correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, correlate_row[-1])->bestcode, + encoder->io_word, &codewordlen); + cur_row[0].a = (family.xlatL2U[correlate_row[0]] + prev_row[0].a) & bpc_mask; + decode_eatbits(encoder, codewordlen); + + if (channel->state.waitcnt) { + --channel->state.waitcnt; + } else { + channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); + update_model(&channel->state, find_bucket(channel, correlate_row[-1]), + correlate_row[0]); + } + stopidx = ++i + channel->state.waitcnt; + } else { + stopidx = i + channel->state.waitcnt; + } + for (;;) { + while (stopidx < end) { + struct s_bucket * pbucket = NULL; + + for (; i <= stopidx; i++) { + unsigned int codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + pbucket = find_bucket(channel, correlate_row[i - 1]); + correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word, + &codewordlen); + FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask); + decode_eatbits(encoder, codewordlen); + } + + update_model(&channel->state, pbucket, correlate_row[stopidx]); + + stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); + } + + for (; i < end; i++) { + unsigned int codewordlen; +#ifdef RLE + RLE_PRED_1_IMP; + RLE_PRED_2_IMP; + RLE_PRED_3_IMP; +#endif + correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel, + correlate_row[i - 1])->bestcode, + encoder->io_word, &codewordlen); + FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask); + decode_eatbits(encoder, codewordlen); + } + + channel->state.waitcnt = stopidx - end; + + return; + +#ifdef RLE +do_run: + channel->state.waitcnt = stopidx - i; + run_index = i; +#ifdef RLE_STAT + run_end = i + decode_channel_run(encoder, channel); +#else + run_end = i + decode_run(encoder); +#endif + + for (; i < run_end; i++) { + cur_row[i].a = cur_row[i - 1].a; + } + + if (i == end) { + return; + } + + stopidx = i + channel->state.waitcnt; +#endif + } +} + +static void FNAME(uncompress_row)(Encoder *encoder, Channel *channel, + const PIXEL * const prev_row, + PIXEL * const cur_row, + unsigned int width) + +{ + const unsigned int bpc = BPC; + const unsigned int bpc_mask = BPC_MASK; + BYTE * const correlate_row = channel->correlate_row; + unsigned int pos = 0; + + while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { + if (channel->state.wmileft) { + FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos, + pos + channel->state.wmileft, bpc, bpc_mask); + pos += channel->state.wmileft; + width -= channel->state.wmileft; + } + + channel->state.wmidx++; + set_wm_trigger(&channel->state); + channel->state.wmileft = wminext; + } + + if (width) { + FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos, + pos + width, bpc, bpc_mask); + if (wmimax > (int)channel->state.wmidx) { + channel->state.wmileft -= width; + } + } + + spice_assert((int)channel->state.wmidx <= wmimax); + spice_assert(channel->state.wmidx <= 32); + spice_assert(wminext > 0); +} + +#undef PIXEL +#undef FNAME +#undef _PIXEL_A +#undef _PIXEL_B +#undef _PIXEL_C +#undef RLE_PRED_1_IMP +#undef RLE_PRED_2_IMP +#undef RLE_PRED_3_IMP +#undef golomb_coding +#undef golomb_deoding +#undef update_model +#undef find_bucket +#undef family +#undef BPC +#undef BPC_MASK diff --git a/spice-common/common/rect.h b/spice-common/common/rect.h new file mode 100644 index 0000000..8c9faed --- /dev/null +++ b/spice-common/common/rect.h @@ -0,0 +1,150 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_RECT +#define _H_RECT + +#include +#include "draw.h" +#include "log.h" + +SPICE_BEGIN_DECLS + +static inline void rect_sect(SpiceRect* r, const SpiceRect* bounds) +{ + r->left = MAX(r->left, bounds->left); + r->right = MIN(r->right, bounds->right); + r->right = MAX(r->left, r->right); + + r->top = MAX(r->top, bounds->top); + r->bottom = MIN(r->bottom, bounds->bottom); + r->bottom = MAX(r->top, r->bottom); +} + +static inline void rect_offset(SpiceRect* r, int dx, int dy) +{ + r->left += dx; + r->right += dx; + r->top += dy; + r->bottom += dy; +} + +static inline int rect_is_empty(const SpiceRect* r) +{ + return r->top == r->bottom || r->left == r->right; +} + +static inline int rect_intersects(const SpiceRect* r1, const SpiceRect* r2) +{ + return r1->left < r2->right && r1->right > r2->left && + r1->top < r2->bottom && r1->bottom > r2->top; +} + +static inline int rect_is_equal(const SpiceRect *r1, const SpiceRect *r2) +{ + return r1->top == r2->top && r1->left == r2->left && + r1->bottom == r2->bottom && r1->right == r2->right; +} + +static inline void rect_union(SpiceRect *dest, const SpiceRect *r) +{ + dest->top = MIN(dest->top, r->top); + dest->left = MIN(dest->left, r->left); + dest->bottom = MAX(dest->bottom, r->bottom); + dest->right = MAX(dest->right, r->right); +} + +static inline int rect_is_same_size(const SpiceRect *r1, const SpiceRect *r2) +{ + return r1->right - r1->left == r2->right - r2->left && + r1->bottom - r1->top == r2->bottom - r2->top; +} + +static inline int rect_contains(const SpiceRect *big, const SpiceRect *small) +{ + return big->left <= small->left && big->right >= small->right && + big->top <= small->top && big->bottom >= small->bottom; +} + +static inline int rect_get_area(const SpiceRect *r) +{ + return (r->right - r->left) * (r->bottom - r->top); +} + +static inline void rect_debug(const SpiceRect *r) +{ + spice_debug("(%d, %d) (%d, %d)", r->left, r->top, r->right, r->bottom); +} + +SPICE_END_DECLS + +#ifdef __cplusplus + +static inline void rect_sect(SpiceRect& r, const SpiceRect& bounds) +{ + rect_sect(&r, &bounds); +} + +static inline void rect_offset(SpiceRect& r, int dx, int dy) +{ + rect_offset(&r, dx, dy); +} + +static inline int rect_is_empty(const SpiceRect& r) +{ + return rect_is_empty(&r); +} + +static inline int rect_intersects(const SpiceRect& r1, const SpiceRect& r2) +{ + return rect_intersects(&r1, &r2); +} + +static inline int rect_is_equal(const SpiceRect& r1, const SpiceRect& r2) +{ + return rect_is_equal(&r1, &r2); +} + +static inline void rect_union(SpiceRect& dest, const SpiceRect& r) +{ + rect_union(&dest, &r); +} + +static inline int rect_is_same_size(const SpiceRect& r1, const SpiceRect& r2) +{ + return rect_is_same_size(&r1, &r2); +} + +static inline int rect_contains(const SpiceRect& big, const SpiceRect& small) +{ + return rect_contains(&big, &small); +} + +static inline int rect_get_area(const SpiceRect& r) +{ + return rect_get_area(&r); +} + +static inline void rect_debug(const SpiceRect &r) +{ + rect_debug(&r); +} + +#endif /* __cplusplus */ + +#endif diff --git a/spice-common/common/region.c b/spice-common/common/region.c new file mode 100644 index 0000000..14a27ed --- /dev/null +++ b/spice-common/common/region.c @@ -0,0 +1,901 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "region.h" +#include "rect.h" +#include "mem.h" + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1, r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* true iff Box r1 contains Box r2 */ +#define SUBSUMES(r1, r2) \ + ( ((r1)->x1 <= (r2)->x1) && \ + ((r1)->x2 >= (r2)->x2) && \ + ((r1)->y1 <= (r2)->y1) && \ + ((r1)->y2 >= (r2)->y2) ) + + +void region_init(QRegion *rgn) +{ + pixman_region32_init(rgn); +} + +void region_clear(QRegion *rgn) +{ + pixman_region32_fini(rgn); + pixman_region32_init(rgn); +} + +void region_destroy(QRegion *rgn) +{ + pixman_region32_fini(rgn); +} + +void region_clone(QRegion *dest, const QRegion *src) +{ + pixman_region32_init(dest); + pixman_region32_copy(dest, (pixman_region32_t *)src); +} + +#define FIND_BAND(r, r_band_end, r_end, ry1) \ + do { \ + ry1 = r->y1; \ + r_band_end = r + 1; \ + while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \ + r_band_end++; \ + } \ + } while (0) + +static int test_band(int query, + int res, + pixman_box32_t *r1, + pixman_box32_t *r1_end, + pixman_box32_t *r2, + pixman_box32_t *r2_end) +{ + int x1; + int x2; + + do { + x1 = MAX(r1->x1, r2->x1); + x2 = MIN(r1->x2, r2->x2); + + /* + * Is there any overlap between the two rectangles? + */ + if (x1 < x2) { + res |= REGION_TEST_SHARED; + + if (r1->x1 < r2->x1 || r1->x2 > r2->x2) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } + + if (r2->x1 < r1->x1 || r2->x2 > r1->x2) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + } else { + /* No overlap at all, the leftmost is exclusive */ + if (r1->x1 < r2->x1) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } else { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + } + + if ((res & query) == query) { + return res; + } + + /* + * Advance the pointer(s) with the leftmost right side, since the next + * rectangle on that list may still overlap the other region's + * current rectangle. + */ + if (r1->x2 == x2) { + r1++; + } + if (r2->x2 == x2) { + r2++; + } + } while ((r1 != r1_end) && (r2 != r2_end)); + + /* + * Deal with whichever band (if any) still has rectangles left. + */ + if (r1 != r1_end) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } else if (r2 != r2_end) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + + return res; +} + +static int test_generic (pixman_region32_t *reg1, + pixman_region32_t *reg2, + int query) +{ + pixman_box32_t *r1; /* Pointer into first region */ + pixman_box32_t *r2; /* Pointer into 2d region */ + pixman_box32_t *r1_end; /* End of 1st region */ + pixman_box32_t *r2_end; /* End of 2d region */ + int ybot; /* Bottom of intersection */ + int ytop; /* Top of intersection */ + pixman_box32_t * r1_band_end; /* End of current band in r1 */ + pixman_box32_t * r2_band_end; /* End of current band in r2 */ + int top; /* Top of non-overlapping band */ + int bot; /* Bottom of non-overlapping band*/ + int r1y1; /* Temps for r1->y1 and r2->y1 */ + int r2y1; + int r1_num_rects; + int r2_num_rects; + int res; + + r1 = pixman_region32_rectangles(reg1, &r1_num_rects); + r1_end = r1 + r1_num_rects; + + r2 = pixman_region32_rectangles(reg2, &r2_num_rects); + r2_end = r2 + r2_num_rects; + + res = 0; + + /* + * Initialize ybot. + * In the upcoming loop, ybot and ytop serve different functions depending + * on whether the band being handled is an overlapping or non-overlapping + * band. + * In the case of a non-overlapping band (only one of the regions + * has points in the band), ybot is the bottom of the most recent + * intersection and thus clips the top of the rectangles in that band. + * ytop is the top of the next intersection between the two regions and + * serves to clip the bottom of the rectangles in the current band. + * For an overlapping band (where the two regions intersect), ytop clips + * the top of the rectangles of both regions and ybot clips the bottoms. + */ + + ybot = MIN(r1->y1, r2->y1); + + do { + /* + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1_band_end and r2_band_end serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + FIND_BAND(r1, r1_band_end, r1_end, r1y1); + FIND_BAND(r2, r2_band_end, r2_end, r2y1); + + /* + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1y1 < r2y1) { + top = MAX (r1y1, ybot); + bot = MIN (r1->y2, r2y1); + if (top != bot) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + + if ((res & query) == query) { + return res & query; + } + } + + ytop = r2y1; + } else if (r2y1 < r1y1) { + top = MAX (r2y1, ybot); + bot = MIN (r2->y2, r1y1); + + if (top != bot) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + + if ((res & query) == query) { + return res & query; + } + } + ytop = r1y1; + } else { + ytop = r1y1; + } + + /* + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = MIN (r1->y2, r2->y2); + if (ybot > ytop) { + res = test_band(query, res, + r1, r1_band_end, + r2, r2_band_end); + if ((res & query) == query) { + return res & query; + } + } + + /* + * If we've finished with a band (y2 == ybot) we skip forward + * in the region to the next band. + */ + if (r1->y2 == ybot) { + r1 = r1_band_end; + } + + if (r2->y2 == ybot) { + r2 = r2_band_end; + } + + } + while (r1 != r1_end && r2 != r2_end); + + /* + * Deal with whichever region (if any) still has rectangles left. + */ + + if (r1 != r1_end) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } else if (r2 != r2_end) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + + return res & query; +} + +int region_test(const QRegion *_reg1, const QRegion *_reg2, int query) +{ + int res; + pixman_region32_t *reg1 = (pixman_region32_t *)_reg1; + pixman_region32_t *reg2 = (pixman_region32_t *)_reg2; + + query = (query) ? query & REGION_TEST_ALL : REGION_TEST_ALL; + + res = 0; + + if (!pixman_region32_not_empty(reg1) || !pixman_region32_not_empty(reg2) || + !EXTENTCHECK (®1->extents, ®2->extents)) { + /* One or more regions are empty or they are disjoint */ + + if (pixman_region32_not_empty(reg1)) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } + + if (pixman_region32_not_empty(reg2)) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + + return res & query; + } else if (!reg1->data && !reg2->data) { + /* Just two rectangles that intersect */ + res |= REGION_TEST_SHARED; + + if (!SUBSUMES(®1->extents, ®2->extents)) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + + if (!SUBSUMES(®2->extents, ®1->extents)) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } + + return res & query; + } else if (!reg2->data && SUBSUMES (®2->extents, ®1->extents)) { + /* reg2 is just a rect that contains all of reg1 */ + + res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */ + res |= REGION_TEST_RIGHT_EXCLUSIVE; /* reg2 contains all of reg1 and then some */ + + return res & query; + } else if (!reg1->data && SUBSUMES (®1->extents, ®2->extents)) { + /* reg1 is just a rect that contains all of reg2 */ + + res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */ + res |= REGION_TEST_LEFT_EXCLUSIVE; /* reg1 contains all of reg2 and then some */ + + return res & query; + } else if (reg1 == reg2) { + res |= REGION_TEST_SHARED; + return res & query; + } else { + /* General purpose intersection */ + return test_generic (reg1, reg2, query); + } +} + +int region_is_valid(const QRegion *rgn) +{ + return pixman_region32_selfcheck((pixman_region32_t *)rgn); +} + +int region_is_empty(const QRegion *rgn) +{ + return !pixman_region32_not_empty((pixman_region32_t *)rgn); +} + +SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects) +{ + pixman_box32_t *boxes; + SpiceRect *rects; + int n, i; + + boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, &n); + if (num_rects) { + *num_rects = n; + } + rects = spice_new(SpiceRect, n); + for (i = 0; i < n; i++) { + rects[i].left = boxes[i].x1; + rects[i].top = boxes[i].y1; + rects[i].right = boxes[i].x2; + rects[i].bottom = boxes[i].y2; + } + return rects; +} + +void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects) +{ + pixman_box32_t *boxes; + unsigned int n, i; + + boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, (int *)&n); + for (i = 0; i < n && i < num_rects; i++) { + rects[i].left = boxes[i].x1; + rects[i].top = boxes[i].y1; + rects[i].right = boxes[i].x2; + rects[i].bottom = boxes[i].y2; + } + + if (i && i != n) { + unsigned int x; + + for (x = 0; x < (n - num_rects); ++x) { + rects[i - 1].left = MIN(rects[i - 1].left, boxes[i + x].x1); + rects[i - 1].top = MIN(rects[i - 1].top, boxes[i + x].y1); + rects[i - 1].right = MAX(rects[i - 1].right, boxes[i + x].x2); + rects[i - 1].bottom = MAX(rects[i - 1].bottom, boxes[i + x].y2); + } + } +} + +void region_extents(const QRegion *rgn, SpiceRect *r) +{ + pixman_box32_t *extents; + + extents = pixman_region32_extents((pixman_region32_t *)rgn); + + r->left = extents->x1; + r->top = extents->y1; + r->right = extents->x2; + r->bottom = extents->y2; +} + +int region_is_equal(const QRegion *rgn1, const QRegion *rgn2) +{ + return pixman_region32_equal((pixman_region32_t *)rgn1, (pixman_region32_t *)rgn2); +} + +int region_intersects(const QRegion *rgn1, const QRegion *rgn2) +{ + int test_res; + + if (!region_bounds_intersects(rgn1, rgn2)) { + return FALSE; + } + + test_res = region_test(rgn1, rgn2, REGION_TEST_SHARED); + return !!test_res; +} + +int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2) +{ + pixman_box32_t *extents1, *extents2; + + extents1 = pixman_region32_extents((pixman_region32_t *)rgn1); + extents2 = pixman_region32_extents((pixman_region32_t *)rgn2); + + return EXTENTCHECK(extents1, extents2); +} + +int region_contains(const QRegion *rgn, const QRegion *other) +{ + int test_res; + + test_res = region_test(rgn, other, REGION_TEST_RIGHT_EXCLUSIVE); + return !test_res; +} + +int region_contains_point(const QRegion *rgn, int32_t x, int32_t y) +{ + return pixman_region32_contains_point((pixman_region32_t *)rgn, x, y, NULL); +} + +void region_or(QRegion *rgn, const QRegion *other_rgn) +{ + pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn); +} + +void region_and(QRegion *rgn, const QRegion *other_rgn) +{ + pixman_region32_intersect(rgn, rgn, (pixman_region32_t *)other_rgn); +} + +void region_xor(QRegion *rgn, const QRegion *other_rgn) +{ + pixman_region32_t intersection; + + pixman_region32_copy(&intersection, rgn); + pixman_region32_intersect(&intersection, + &intersection, + (pixman_region32_t *)other_rgn); + pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn); + pixman_region32_subtract(rgn, rgn, &intersection); + pixman_region32_fini(&intersection); +} + +void region_exclude(QRegion *rgn, const QRegion *other_rgn) +{ + pixman_region32_subtract(rgn, rgn, (pixman_region32_t *)other_rgn); +} + +void region_add(QRegion *rgn, const SpiceRect *r) +{ + pixman_region32_union_rect(rgn, rgn, r->left, r->top, + r->right - r->left, + r->bottom - r->top); +} + +void region_remove(QRegion *rgn, const SpiceRect *r) +{ + pixman_region32_t rg; + + pixman_region32_init_rect(&rg, r->left, r->top, + r->right - r->left, + r->bottom - r->top); + pixman_region32_subtract(rgn, rgn, &rg); + pixman_region32_fini(&rg); +} + + +void region_offset(QRegion *rgn, int32_t dx, int32_t dy) +{ + pixman_region32_translate(rgn, dx, dy); +} + +void region_dump(const QRegion *rgn, const char *prefix) +{ + pixman_box32_t *rects, *extents; + int n_rects, i; + + printf("%sREGION: %p, ", prefix, rgn); + + if (!pixman_region32_not_empty((pixman_region32_t *)rgn)) { + printf("EMPTY\n"); + return; + } + + extents = pixman_region32_extents((pixman_region32_t *)rgn); + rects = pixman_region32_rectangles((pixman_region32_t *)rgn, &n_rects); + printf("num %u bounds (%d, %d, %d, %d)\n", + n_rects, + extents->x1, + extents->y1, + extents->x2, + extents->y2); + + + for (i = 0; i < n_rects; i++) { + printf("%*s %12d %12d %12d %12d\n", + (int)strlen(prefix), "", + rects[i].x1, + rects[i].y1, + rects[i].x2, + rects[i].y2); + } +} + +#ifdef REGION_TEST + +static int slow_region_test(const QRegion *rgn, const QRegion *other_rgn, int query) +{ + pixman_region32_t intersection; + int res; + + pixman_region32_init(&intersection); + pixman_region32_intersect(&intersection, + (pixman_region32_t *)rgn, + (pixman_region32_t *)other_rgn); + + res = 0; + + if (query & REGION_TEST_SHARED && + pixman_region32_not_empty(&intersection)) { + res |= REGION_TEST_SHARED; + } + + if (query & REGION_TEST_LEFT_EXCLUSIVE && + !pixman_region32_equal(&intersection, (pixman_region32_t *)rgn)) { + res |= REGION_TEST_LEFT_EXCLUSIVE; + } + + if (query & REGION_TEST_RIGHT_EXCLUSIVE && + !pixman_region32_equal(&intersection, (pixman_region32_t *)other_rgn)) { + res |= REGION_TEST_RIGHT_EXCLUSIVE; + } + + pixman_region32_fini(&intersection); + + return res; +} + + +static int rect_is_valid(const SpiceRect *r) +{ + if (r->top > r->bottom || r->left > r->right) { + printf("%s: invalid rect\n", __FUNCTION__); + return FALSE; + } + return TRUE; +} + +static void rect_set(SpiceRect *r, int32_t top, int32_t left, int32_t bottom, int32_t right) +{ + r->top = top; + r->left = left; + r->bottom = bottom; + r->right = right; + spice_assert(rect_is_valid(r)); +} + +static void random_region(QRegion *reg) +{ + int i; + int num_rects; + int x, y, w, h; + SpiceRect _r; + SpiceRect *r = &_r; + + region_clear(reg); + + num_rects = rand() % 20; + for (i = 0; i < num_rects; i++) { + x = rand()%100; + y = rand()%100; + w = rand()%100; + h = rand()%100; + rect_set(r, + x, y, + x+w, y+h); + region_add(reg, r); + } +} + +static void test(const QRegion *r1, const QRegion *r2, int *expected) +{ + printf("r1 is_empty %s [%s]\n", + region_is_empty(r1) ? "TRUE" : "FALSE", + (region_is_empty(r1) == *(expected++)) ? "OK" : "ERR"); + printf("r2 is_empty %s [%s]\n", + region_is_empty(r2) ? "TRUE" : "FALSE", + (region_is_empty(r2) == *(expected++)) ? "OK" : "ERR"); + printf("is_equal %s [%s]\n", + region_is_equal(r1, r2) ? "TRUE" : "FALSE", + (region_is_equal(r1, r2) == *(expected++)) ? "OK" : "ERR"); + printf("intersects %s [%s]\n", + region_intersects(r1, r2) ? "TRUE" : "FALSE", + (region_intersects(r1, r2) == *(expected++)) ? "OK" : "ERR"); + printf("contains %s [%s]\n", + region_contains(r1, r2) ? "TRUE" : "FALSE", + (region_contains(r1, r2) == *(expected++)) ? "OK" : "ERR"); +} + +enum { + EXPECT_R1_EMPTY, + EXPECT_R2_EMPTY, + EXPECT_EQUAL, + EXPECT_SECT, + EXPECT_CONT, +}; + +int main(void) +{ + QRegion _r1, _r2, _r3; + QRegion *r1 = &_r1; + QRegion *r2 = &_r2; + QRegion *r3 = &_r3; + SpiceRect _r; + SpiceRect *r = &_r; + int expected[5]; + int i, j; + + region_init(r1); + region_init(r2); + + printf("dump r1 empty rgn [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = TRUE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = TRUE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clone(r3, r1); + printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID"); + region_dump(r3, ""); + expected[EXPECT_R1_EMPTY] = TRUE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = TRUE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r3, expected); + region_destroy(r3); + printf("\n"); + + rect_set(r, 0, 0, 100, 100); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r1); + rect_set(r, 0, 0, 0, 0); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = TRUE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = TRUE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + rect_set(r, -100, -100, 0, 0); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r1); + rect_set(r, -100, -100, 100, 100); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + + region_clear(r1); + region_clear(r2); + + rect_set(r, 100, 100, 200, 200); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + rect_set(r, 300, 300, 400, 400); + region_add(r1, r); + printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); + region_dump(r1, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = TRUE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + rect_set(r, 500, 500, 600, 600); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = FALSE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, 100, 100, 200, 200); + region_add(r2, r); + rect_set(r, 300, 300, 400, 400); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = TRUE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, 100, 100, 200, 200); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, -2000, -2000, -1000, -1000); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = FALSE; + expected[EXPECT_CONT] = FALSE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, -2000, -2000, 1000, 1000); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = FALSE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, 150, 150, 175, 175); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = TRUE; + test(r1, r2, expected); + printf("\n"); + + region_clear(r2); + + rect_set(r, 150, 150, 350, 350); + region_add(r2, r); + printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = FALSE; + test(r1, r2, expected); + printf("\n"); + + region_and(r2, r1); + printf("dump r2 and r1 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); + region_dump(r2, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = FALSE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = FALSE; + test(r2, r1, expected); + printf("\n"); + + + region_clone(r3, r1); + printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID"); + region_dump(r3, ""); + expected[EXPECT_R1_EMPTY] = FALSE; + expected[EXPECT_R2_EMPTY] = FALSE; + expected[EXPECT_EQUAL] = TRUE; + expected[EXPECT_SECT] = TRUE; + expected[EXPECT_CONT] = TRUE; + test(r1, r3, expected); + printf("\n"); + + j = 0; + for (i = 0; i < 1000000; i++) { + int res1, res2, test; + int tests[] = { + REGION_TEST_LEFT_EXCLUSIVE, + REGION_TEST_RIGHT_EXCLUSIVE, + REGION_TEST_SHARED, + REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE, + REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_SHARED, + REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED, + REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED + }; + + random_region(r1); + random_region(r2); + + for (test = 0; test < 7; test++) { + res1 = region_test(r1, r2, tests[test]); + res2 = slow_region_test(r1, r2, tests[test]); + if (res1 != res2) { + printf ("Error in region_test %d, got %d, expected %d, query=%d\n", + j, res1, res2, tests[test]); + printf ("r1:\n"); + region_dump(r1, ""); + printf ("r2:\n"); + region_dump(r2, ""); + } + j++; + } + } + + region_destroy(r3); + region_destroy(r1); + region_destroy(r2); + + return 0; +} + +#endif diff --git a/spice-common/common/region.h b/spice-common/common/region.h new file mode 100644 index 0000000..4619406 --- /dev/null +++ b/spice-common/common/region.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_REGION +#define _H_REGION + +#include +#include + +#include "draw.h" +#include "pixman_utils.h" + +SPICE_BEGIN_DECLS + +typedef pixman_region32_t QRegion; + +#define REGION_TEST_LEFT_EXCLUSIVE (1 << 0) +#define REGION_TEST_RIGHT_EXCLUSIVE (1 << 1) +#define REGION_TEST_SHARED (1 << 2) +#define REGION_TEST_ALL \ + (REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED) + +void region_init(QRegion *rgn); +void region_clear(QRegion *rgn); +void region_destroy(QRegion *rgn); +void region_clone(QRegion *dest, const QRegion *src); +SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects); +void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects); +void region_extents(const QRegion *rgn, SpiceRect *r); + +int region_test(const QRegion *rgn, const QRegion *other_rgn, int query); +int region_is_valid(const QRegion *rgn); +int region_is_empty(const QRegion *rgn); +int region_is_equal(const QRegion *rgn1, const QRegion *rgn2); +int region_intersects(const QRegion *rgn1, const QRegion *rgn2); +int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2); +int region_contains(const QRegion *rgn, const QRegion *other); +int region_contains_point(const QRegion *rgn, int32_t x, int32_t y); + +void region_or(QRegion *rgn, const QRegion *other_rgn); +void region_and(QRegion *rgn, const QRegion *other_rgn); +void region_xor(QRegion *rgn, const QRegion *other_rgn); +void region_exclude(QRegion *rgn, const QRegion *other_rgn); + +void region_add(QRegion *rgn, const SpiceRect *r); +void region_remove(QRegion *rgn, const SpiceRect *r); + +void region_offset(QRegion *rgn, int32_t dx, int32_t dy); + + +void region_dump(const QRegion *rgn, const char *prefix); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/ring.h b/spice-common/common/ring.h new file mode 100644 index 0000000..b13bc7d --- /dev/null +++ b/spice-common/common/ring.h @@ -0,0 +1,168 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_RING2 +#define _H_RING2 + +#include "spice_common.h" + +SPICE_BEGIN_DECLS + +typedef struct Ring RingItem; +typedef struct Ring { + RingItem *prev; + RingItem *next; +} Ring; + +static inline void ring_init(Ring *ring) +{ + ring->next = ring->prev = ring; +} + +static inline void ring_item_init(RingItem *item) +{ + item->next = item->prev = NULL; +} + +static inline int ring_item_is_linked(RingItem *item) +{ + return !!item->next; +} + +static inline int ring_is_empty(Ring *ring) +{ + spice_assert(ring->next != NULL && ring->prev != NULL); + return ring == ring->next; +} + +static inline void ring_add(Ring *ring, RingItem *item) +{ + spice_assert(ring->next != NULL && ring->prev != NULL); + spice_assert(item->next == NULL && item->prev == NULL); + + item->next = ring->next; + item->prev = ring; + ring->next = item->next->prev = item; +} + +static inline void ring_add_after(RingItem *item, RingItem *pos) +{ + ring_add(pos, item); +} + +static inline void ring_add_before(RingItem *item, RingItem *pos) +{ + ring_add(pos->prev, item); +} + +static inline void __ring_remove(RingItem *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + item->prev = item->next = NULL; +} + +static inline void ring_remove(RingItem *item) +{ + spice_assert(item->next != NULL && item->prev != NULL); + spice_assert(item->next != item); + + __ring_remove(item); +} + +static inline RingItem *ring_get_head(Ring *ring) +{ + RingItem *ret; + + spice_assert(ring->next != NULL && ring->prev != NULL); + + if (ring_is_empty(ring)) { + return NULL; + } + ret = ring->next; + return ret; +} + +static inline RingItem *ring_get_tail(Ring *ring) +{ + RingItem *ret; + + spice_assert(ring->next != NULL && ring->prev != NULL); + + if (ring_is_empty(ring)) { + return NULL; + } + ret = ring->prev; + return ret; +} + +static inline RingItem *ring_next(Ring *ring, RingItem *pos) +{ + RingItem *ret; + + spice_assert(ring->next != NULL && ring->prev != NULL); + spice_assert(pos); + spice_assert(pos->next != NULL && pos->prev != NULL); + ret = pos->next; + return (ret == ring) ? NULL : ret; +} + +static inline RingItem *ring_prev(Ring *ring, RingItem *pos) +{ + RingItem *ret; + + spice_assert(ring->next != NULL && ring->prev != NULL); + spice_assert(pos); + spice_assert(pos->next != NULL && pos->prev != NULL); + ret = pos->prev; + return (ret == ring) ? NULL : ret; +} + +#define RING_FOREACH_SAFE(var, next, ring) \ + for ((var) = ring_get_head(ring); \ + (var) && ((next) = ring_next(ring, (var)), 1); \ + (var) = (next)) + + +#define RING_FOREACH(var, ring) \ + for ((var) = ring_get_head(ring); \ + (var); \ + (var) = ring_next(ring, var)) + +#define RING_FOREACH_REVERSED(var, ring) \ + for ((var) = ring_get_tail(ring); \ + (var); \ + (var) = ring_prev(ring, var)) + + +static inline unsigned int ring_get_length(Ring *ring) +{ + RingItem *i; + unsigned int ret = 0; + + for (i = ring_get_head(ring); + i != NULL; + i = ring_next(ring, i)) + ret++; + + return ret; +} + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/rop3.c b/spice-common/common/rop3.c new file mode 100644 index 0000000..2a0a167 --- /dev/null +++ b/spice-common/common/rop3.c @@ -0,0 +1,646 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "rop3.h" +#include "spice_common.h" + +typedef void (*rop3_with_pattern_handler_t)(pixman_image_t *d, pixman_image_t *s, + SpicePoint *src_pos, pixman_image_t *p, + SpicePoint *pat_pos); + +typedef void (*rop3_with_color_handler_t)(pixman_image_t *d, pixman_image_t *s, + SpicePoint *src_pos, uint32_t rgb); + +typedef void (*rop3_test_handler_t)(void); + +#define ROP3_NUM_OPS 256 + +static rop3_with_pattern_handler_t rop3_with_pattern_handlers_32[ROP3_NUM_OPS]; +static rop3_with_pattern_handler_t rop3_with_pattern_handlers_16[ROP3_NUM_OPS]; +static rop3_with_color_handler_t rop3_with_color_handlers_32[ROP3_NUM_OPS]; +static rop3_with_color_handler_t rop3_with_color_handlers_16[ROP3_NUM_OPS]; +static rop3_test_handler_t rop3_test_handlers_32[ROP3_NUM_OPS]; +static rop3_test_handler_t rop3_test_handlers_16[ROP3_NUM_OPS]; + + +static void default_rop3_with_pattern_handler(SPICE_GNUC_UNUSED pixman_image_t *d, + SPICE_GNUC_UNUSED pixman_image_t *s, + SPICE_GNUC_UNUSED SpicePoint *src_pos, + SPICE_GNUC_UNUSED pixman_image_t *p, + SPICE_GNUC_UNUSED SpicePoint *pat_pos) +{ + spice_critical("not implemented"); +} + +static void default_rop3_withe_color_handler(SPICE_GNUC_UNUSED pixman_image_t *d, + SPICE_GNUC_UNUSED pixman_image_t *s, + SPICE_GNUC_UNUSED SpicePoint *src_pos, + SPICE_GNUC_UNUSED uint32_t rgb) +{ + spice_critical("not implemented"); +} + +static void default_rop3_test_handler(void) +{ +} + +#define ROP3_HANDLERS_DEPTH(name, formula, index, depth) \ +static void rop3_handle_p##depth##_##name(pixman_image_t *d, pixman_image_t *s, \ + SpicePoint *src_pos, \ + pixman_image_t *p, SpicePoint *pat_pos) \ +{ \ + int width = pixman_image_get_width(d); \ + int height = pixman_image_get_height(d); \ + uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \ + int dest_stride = pixman_image_get_stride(d); \ + uint8_t *end_line = dest_line + height * dest_stride; \ + \ + int pat_width = pixman_image_get_width(p); \ + int pat_height = pixman_image_get_height(p); \ + uint8_t *pat_base = (uint8_t *)pixman_image_get_data(p); \ + int pat_stride = pixman_image_get_stride(p); \ + int pat_v_offset = pat_pos->y; \ + \ + int src_stride = pixman_image_get_stride(s); \ + uint8_t *src_line; \ + src_line = (uint8_t *)pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \ + \ + for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \ + uint##depth##_t *dest = (uint##depth##_t *)dest_line; \ + uint##depth##_t *end = dest + width; \ + uint##depth##_t *src = (uint##depth##_t *)src_line; \ + \ + int pat_h_offset = pat_pos->x; \ + \ + for (; dest < end; dest++, src++) { \ + uint##depth##_t *pat; \ + pat = (uint##depth##_t *) \ + (pat_base + pat_v_offset * pat_stride + (pat_h_offset * depth / 8)); \ + *dest = formula; \ + pat_h_offset = (pat_h_offset + 1) % pat_width; \ + } \ + \ + pat_v_offset = (pat_v_offset + 1) % pat_height; \ + } \ +} \ + \ +static void rop3_handle_c##depth##_##name(pixman_image_t *d, pixman_image_t *s, \ + SpicePoint *src_pos, \ + uint32_t rgb) \ +{ \ + int width = pixman_image_get_width(d); \ + int height = pixman_image_get_height(d); \ + uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \ + int dest_stride = pixman_image_get_stride(d); \ + uint8_t *end_line = dest_line + height * dest_stride; \ + uint##depth##_t _pat = rgb; \ + uint##depth##_t *pat = &_pat; \ + \ + int src_stride = pixman_image_get_stride(s); \ + uint8_t *src_line; \ + src_line = (uint8_t *) \ + pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \ + \ + for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \ + uint##depth##_t *dest = (uint##depth##_t *)dest_line; \ + uint##depth##_t *end = dest + width; \ + uint##depth##_t *src = (uint##depth##_t *)src_line; \ + for (; dest < end; dest++, src++) { \ + *dest = formula; \ + } \ + } \ +} \ + \ +static void rop3_test##depth##_##name(void) \ +{ \ + uint8_t d = 0xaa; \ + uint8_t s = 0xcc; \ + uint8_t p = 0xf0; \ + uint8_t *pat = &p; \ + uint8_t *src = &s; \ + uint8_t *dest = &d; \ + \ + d = formula; \ + if (d != index) { \ + printf("%s: failed, result is 0x%x expect 0x%x\n", __FUNCTION__, d, index); \ + } \ +} + +#define ROP3_HANDLERS(name, formula, index) \ + ROP3_HANDLERS_DEPTH(name, formula, index, 32) \ + ROP3_HANDLERS_DEPTH(name, formula, index, 16) + +ROP3_HANDLERS(DPSoon, ~(*pat | *src | *dest), 0x01); +ROP3_HANDLERS(DPSona, ~(*pat | *src) & *dest, 0x02); +ROP3_HANDLERS(SDPona, ~(*pat | *dest) & *src, 0x04); +ROP3_HANDLERS(PDSxnon, ~(~(*src ^ *dest) | *pat), 0x06); +ROP3_HANDLERS(PDSaon, ~((*src & *dest) | *pat), 0x07); +ROP3_HANDLERS(SDPnaa, ~*pat & *dest & *src, 0x08); +ROP3_HANDLERS(PDSxon, ~((*src ^ *dest) | *pat), 0x09); +ROP3_HANDLERS(PSDnaon, ~((~*dest & *src) | *pat), 0x0b); +ROP3_HANDLERS(PDSnaon, ~((~*src & *dest) | *pat), 0x0d); +ROP3_HANDLERS(PDSonon, ~(~(*src | *dest) | *pat), 0x0e); +ROP3_HANDLERS(PDSona, ~(*src | *dest) & *pat, 0x10); +ROP3_HANDLERS(SDPxnon, ~(~(*pat ^ *dest) | *src), 0x12); +ROP3_HANDLERS(SDPaon, ~((*pat & *dest) | *src), 0x13); +ROP3_HANDLERS(DPSxnon, ~(~(*pat ^ *src) | *dest), 0x14); +ROP3_HANDLERS(DPSaon, ~((*pat & *src) | *dest), 0x15); +ROP3_HANDLERS(PSDPSanaxx, (~(*pat & *src) & *dest) ^ *src ^ *pat, 0x16); +ROP3_HANDLERS(SSPxDSxaxn, ~(((*src ^ *dest) & (*src ^ *pat)) ^ *src), 0x17); +ROP3_HANDLERS(SPxPDxa, (*src ^ *pat) & (*pat ^ *dest), 0x18); +ROP3_HANDLERS(SDPSanaxn, ~((~(*pat & *src) & *dest) ^ *src), 0x19); +ROP3_HANDLERS(PDSPaox, ((*pat & *src) | *dest) ^ *pat, 0x1a); +ROP3_HANDLERS(SDPSxaxn, ~(((*pat ^ *src) & *dest) ^ *src), 0x1b); +ROP3_HANDLERS(PSDPaox, ((*pat & *dest) | *src) ^ *pat, 0x1c); +ROP3_HANDLERS(DSPDxaxn, ~(((*pat ^ *dest) & *src) ^ *dest), 0x1d); +ROP3_HANDLERS(PDSox, (*dest | *src) ^ *pat, 0x1e); +ROP3_HANDLERS(PDSoan, ~((*src | *dest) & *pat), 0x1f); +ROP3_HANDLERS(DPSnaa, ~*src & *pat & *dest, 0x20); +ROP3_HANDLERS(SDPxon, ~((*pat ^ *dest) | *src), 0x21); +ROP3_HANDLERS(SPDnaon, ~((~*dest & *pat) | *src), 0x23); +ROP3_HANDLERS(SPxDSxa, (*src ^ *pat) & (*dest ^ *src), 0x24); +ROP3_HANDLERS(PDSPanaxn, ~((~(*src & *pat) & *dest) ^ *pat), 0x25); +ROP3_HANDLERS(SDPSaox, ((*src & *pat) | *dest) ^ *src, 0x26); +ROP3_HANDLERS(SDPSxnox, (~(*src ^ *pat) | *dest) ^ *src, 0x27); +ROP3_HANDLERS(DPSxa, (*pat ^ *src) & *dest, 0x28); +ROP3_HANDLERS(PSDPSaoxxn, ~(((*src & *pat) | *dest) ^ *src ^ *pat), 0x29); +ROP3_HANDLERS(DPSana, ~(*src & *pat) & *dest, 0x2a); +ROP3_HANDLERS(SSPxPDxaxn, ~(((*pat ^ *dest) & (*src ^ *pat)) ^ *src), 0x2b); +ROP3_HANDLERS(SPDSoax, ((*src | *dest) & *pat) ^ *src, 0x2c); +ROP3_HANDLERS(PSDnox, (~*dest | *src) ^ *pat, 0x2d); +ROP3_HANDLERS(PSDPxox, ((*pat ^ *dest) | *src) ^ *pat, 0x2e); +ROP3_HANDLERS(PSDnoan, ~((~*dest | *src) & *pat), 0x2f); +ROP3_HANDLERS(SDPnaon, ~((~*pat & *dest) | *src), 0x31); +ROP3_HANDLERS(SDPSoox, (*src | *pat | *dest) ^ *src, 0x32); +ROP3_HANDLERS(SPDSaox, ((*src & *dest) | *pat) ^ *src, 0x34); +ROP3_HANDLERS(SPDSxnox, (~(*src ^ *dest) | *pat) ^ *src, 0x35); +ROP3_HANDLERS(SDPox, (*pat | *dest) ^ *src, 0x36); +ROP3_HANDLERS(SDPoan, ~((*pat | *dest) & *src), 0x37); +ROP3_HANDLERS(PSDPoax, ((*pat | *dest) & *src) ^ *pat, 0x38); +ROP3_HANDLERS(SPDnox, (~*dest | *pat) ^ *src, 0x39); +ROP3_HANDLERS(SPDSxox, ((*src ^ *dest) | *pat) ^ *src, 0x3a); +ROP3_HANDLERS(SPDnoan, ~((~*dest | *pat) & *src), 0x3b); +ROP3_HANDLERS(SPDSonox, (~(*src | *dest) | *pat) ^ *src, 0x3d); +ROP3_HANDLERS(SPDSnaox, ((~*src & *dest) | *pat) ^ *src, 0x3e); +ROP3_HANDLERS(PSDnaa, ~*dest & *src & *pat, 0x40); +ROP3_HANDLERS(DPSxon, ~((*src ^ *pat) | *dest), 0x41); +ROP3_HANDLERS(SDxPDxa, (*src ^ *dest) & (*pat ^ *dest), 0x42); +ROP3_HANDLERS(SPDSanaxn, ~((~(*src & *dest) & *pat) ^ *src), 0x43); +ROP3_HANDLERS(DPSnaon, ~((~*src & *pat) | *dest), 0x45); +ROP3_HANDLERS(DSPDaox, ((*dest & *pat) | *src) ^ *dest, 0x46); +ROP3_HANDLERS(PSDPxaxn, ~(((*pat ^ *dest) & *src) ^ *pat), 0x47); +ROP3_HANDLERS(SDPxa, (*pat ^ *dest) & *src, 0x48); +ROP3_HANDLERS(PDSPDaoxxn, ~(((*dest & *pat) | *src) ^ *dest ^ *pat), 0x49); +ROP3_HANDLERS(DPSDoax, ((*dest | *src) & *pat) ^ *dest, 0x4a); +ROP3_HANDLERS(PDSnox, (~*src | *dest) ^ *pat, 0x4b); +ROP3_HANDLERS(SDPana, ~(*pat & *dest) & *src, 0x4c); +ROP3_HANDLERS(SSPxDSxoxn, ~(((*src ^ *dest) | (*src ^ *pat)) ^ *src), 0x4d); +ROP3_HANDLERS(PDSPxox, ((*pat ^ *src) | *dest) ^ *pat, 0x4e); +ROP3_HANDLERS(PDSnoan, ~((~*src | *dest) & *pat), 0x4f); +ROP3_HANDLERS(DSPnaon, ~((~*pat & *src) | *dest), 0x51); +ROP3_HANDLERS(DPSDaox, ((*dest & *src) | *pat) ^ *dest, 0x52); +ROP3_HANDLERS(SPDSxaxn, ~(((*src ^ *dest) & *pat) ^ *src), 0x53); +ROP3_HANDLERS(DPSonon, ~(~(*src | *pat) | *dest), 0x54); +ROP3_HANDLERS(DPSox, (*src | *pat) ^ *dest, 0x56); +ROP3_HANDLERS(DPSoan, ~((*src | *pat) & *dest), 0x57); +ROP3_HANDLERS(PDSPoax, ((*pat | *src) & *dest) ^ *pat, 0x58); +ROP3_HANDLERS(DPSnox, (~*src | *pat) ^ *dest, 0x59); +ROP3_HANDLERS(DPSDonox, (~(*dest | *src) | *pat) ^ *dest, 0x5b); +ROP3_HANDLERS(DPSDxox, ((*dest ^ *src) | *pat) ^ *dest, 0x5c); +ROP3_HANDLERS(DPSnoan, ~((~*src | *pat) & *dest), 0x5d); +ROP3_HANDLERS(DPSDnaox, ((~*dest & *src) | *pat) ^ *dest, 0x5e); +ROP3_HANDLERS(PDSxa, (*src ^ *dest) & *pat, 0x60); +ROP3_HANDLERS(DSPDSaoxxn, ~(((*src & *dest) | *pat) ^ *src ^ *dest), 0x61); +ROP3_HANDLERS(DSPDoax, ((*dest | *pat) & *src) ^ *dest, 0x62); +ROP3_HANDLERS(SDPnox, (~*pat | *dest) ^ *src, 0x63); +ROP3_HANDLERS(SDPSoax, ((*src | *pat) & *dest) ^ *src, 0x64); +ROP3_HANDLERS(DSPnox, (~*pat | *src) ^ *dest, 0x65); +ROP3_HANDLERS(SDPSonox, (~(*src | *pat) | *dest) ^ *src, 0x67); +ROP3_HANDLERS(DSPDSonoxxn, ~((~(*src | *dest) | *pat) ^ *src ^ *dest), 0x68); +ROP3_HANDLERS(PDSxxn, ~(*src ^ *dest ^ *pat), 0x69); +ROP3_HANDLERS(DPSax, (*src & *pat) ^ *dest, 0x6a); +ROP3_HANDLERS(PSDPSoaxxn, ~(((*src | *pat) & *dest) ^ *src ^ *pat), 0x6b); +ROP3_HANDLERS(SDPax, (*pat & *dest) ^ *src, 0x6c); +ROP3_HANDLERS(PDSPDoaxxn, ~(((*dest | *pat) & *src) ^ *dest ^ *pat), 0x6d); +ROP3_HANDLERS(SDPSnoax, ((~*src | *pat) & *dest) ^ *src, 0x6e); +ROP3_HANDLERS(PDSxnan, ~(~(*src ^ *dest) & *pat), 0x6f); +ROP3_HANDLERS(PDSana, ~(*src & *dest) & *pat, 0x70); +ROP3_HANDLERS(SSDxPDxaxn, ~(((*dest ^ *pat) & (*src ^ *dest)) ^ *src), 0x71); +ROP3_HANDLERS(SDPSxox, ((*src ^ *pat) | *dest) ^ *src, 0x72); +ROP3_HANDLERS(SDPnoan, ~((~*pat | *dest) & *src), 0x73); +ROP3_HANDLERS(DSPDxox, ((*dest ^ *pat) | *src) ^ *dest, 0x74); +ROP3_HANDLERS(DSPnoan, ~((~*pat | *src) & *dest), 0x75); +ROP3_HANDLERS(SDPSnaox, ((~*src & *pat) | *dest) ^ *src, 0x76); +ROP3_HANDLERS(PDSax, (*src & *dest) ^ *pat, 0x78); +ROP3_HANDLERS(DSPDSoaxxn, ~(((*src | *dest) & *pat) ^ *src ^ *dest), 0x79); +ROP3_HANDLERS(DPSDnoax, ((~*dest | *src) & *pat) ^ *dest, 0x7a); +ROP3_HANDLERS(SDPxnan, ~(~(*pat ^ *dest) & *src), 0x7b); +ROP3_HANDLERS(SPDSnoax, ((~*src | *dest) & *pat) ^ *src, 0x7c); +ROP3_HANDLERS(DPSxnan, ~(~(*src ^ *pat) & *dest), 0x7d); +ROP3_HANDLERS(SPxDSxo, (*src ^ *dest) | (*pat ^ *src), 0x7e); +ROP3_HANDLERS(DPSaan, ~(*src & *pat & *dest), 0x7f); +ROP3_HANDLERS(DPSaa, *src & *pat & *dest, 0x80); +ROP3_HANDLERS(SPxDSxon, ~((*src ^ *dest) | (*pat ^ *src)), 0x81); +ROP3_HANDLERS(DPSxna, ~(*src ^ *pat) & *dest, 0x82); +ROP3_HANDLERS(SPDSnoaxn, ~(((~*src | *dest) & *pat) ^ *src), 0x83); +ROP3_HANDLERS(SDPxna, ~(*pat ^ *dest) & *src, 0x84); +ROP3_HANDLERS(PDSPnoaxn, ~(((~*pat | *src) & *dest) ^ *pat), 0x85); +ROP3_HANDLERS(DSPDSoaxx, ((*src | *dest) & *pat) ^ *src ^ *dest, 0x86); +ROP3_HANDLERS(PDSaxn, ~((*src & *dest) ^ *pat), 0x87); +ROP3_HANDLERS(SDPSnaoxn, ~(((~*src & *pat) | *dest) ^ *src), 0x89); +ROP3_HANDLERS(DSPnoa, (~*pat | *src) & *dest, 0x8a); +ROP3_HANDLERS(DSPDxoxn, ~(((*dest ^ *pat) | *src) ^ *dest), 0x8b); +ROP3_HANDLERS(SDPnoa, (~*pat | *dest) & *src, 0x8c); +ROP3_HANDLERS(SDPSxoxn, ~(((*src ^ *pat) | *dest) ^ *src), 0x8d); +ROP3_HANDLERS(SSDxPDxax, ((*dest ^ *pat) & (*dest ^ *src)) ^ *src, 0x8e); +ROP3_HANDLERS(PDSanan, ~(~(*src & *dest) & *pat), 0x8f); +ROP3_HANDLERS(PDSxna, ~(*src ^ *dest) & *pat, 0x90); +ROP3_HANDLERS(SDPSnoaxn, ~(((~*src | *pat) & *dest) ^ *src), 0x91); +ROP3_HANDLERS(DPSDPoaxx, ((*pat | *dest) & *src) ^ *pat ^ *dest, 0x92); +ROP3_HANDLERS(SPDaxn, ~((*dest & *pat) ^ *src), 0x93); +ROP3_HANDLERS(PSDPSoaxx, ((*src | *pat) & *dest) ^ *src ^ *pat, 0x94); +ROP3_HANDLERS(DPSaxn, ~((*src & *pat) ^ *dest), 0x95); +ROP3_HANDLERS(DPSxx, *src ^ *pat ^ *dest, 0x96); +ROP3_HANDLERS(PSDPSonoxx, (~(*src | *pat) | *dest) ^ *src ^ *pat, 0x97); +ROP3_HANDLERS(SDPSonoxn, ~((~(*src | *pat) | *dest) ^ *src), 0x98); +ROP3_HANDLERS(DPSnax, (~*src & *pat) ^ *dest, 0x9a); +ROP3_HANDLERS(SDPSoaxn, ~(((*src | *pat) & *dest) ^ *src), 0x9b); +ROP3_HANDLERS(SPDnax, (~*dest & *pat) ^ *src, 0x9c); +ROP3_HANDLERS(DSPDoaxn, ~(((*dest | *pat) & *src) ^ *dest), 0x9d); +ROP3_HANDLERS(DSPDSaoxx, ((*src & *dest) | *pat) ^ *src ^ *dest, 0x9e); +ROP3_HANDLERS(PDSxan, ~((*src ^ *dest) & *pat), 0x9f); +ROP3_HANDLERS(PDSPnaoxn, ~(((~*pat & *src) | *dest) ^ *pat), 0xa1); +ROP3_HANDLERS(DPSnoa, (~*src | *pat) & *dest, 0xa2); +ROP3_HANDLERS(DPSDxoxn, ~(((*dest ^ *src) | *pat) ^ *dest), 0xa3); +ROP3_HANDLERS(PDSPonoxn, ~((~(*pat | *src) | *dest) ^ *pat), 0xa4); +ROP3_HANDLERS(DSPnax, (~*pat & *src) ^ *dest, 0xa6); +ROP3_HANDLERS(PDSPoaxn, ~(((*pat | *src) & *dest) ^ *pat), 0xa7); +ROP3_HANDLERS(DPSoa, (*src | *pat) & *dest, 0xa8); +ROP3_HANDLERS(DPSoxn, ~((*src | *pat) ^ *dest), 0xa9); +ROP3_HANDLERS(DPSono, ~(*src | *pat) | *dest, 0xab); +ROP3_HANDLERS(SPDSxax, ((*src ^ *dest) & *pat) ^ *src, 0xac); +ROP3_HANDLERS(DPSDaoxn, ~(((*dest & *src) | *pat) ^ *dest), 0xad); +ROP3_HANDLERS(DSPnao, (~*pat & *src) | *dest, 0xae); +ROP3_HANDLERS(PDSnoa, (~*src | *dest) & *pat, 0xb0); +ROP3_HANDLERS(PDSPxoxn, ~(((*pat ^ *src) | *dest) ^ *pat), 0xb1); +ROP3_HANDLERS(SSPxDSxox, ((*src ^ *dest) | (*pat ^ *src)) ^ *src, 0xb2); +ROP3_HANDLERS(SDPanan, ~(~(*pat & *dest) & *src), 0xb3); +ROP3_HANDLERS(PSDnax, (~*dest & *src) ^ *pat, 0xb4); +ROP3_HANDLERS(DPSDoaxn, ~(((*dest | *src) & *pat) ^ *dest), 0xb5); +ROP3_HANDLERS(DPSDPaoxx, ((*pat & *dest) | *src) ^ *pat ^ *dest, 0xb6); +ROP3_HANDLERS(SDPxan, ~((*pat ^ *dest) & *src), 0xb7); +ROP3_HANDLERS(PSDPxax, ((*dest ^ *pat) & *src) ^ *pat, 0xb8); +ROP3_HANDLERS(DSPDaoxn, ~(((*dest & *pat) | *src) ^ *dest), 0xb9); +ROP3_HANDLERS(DPSnao, (~*src & *pat) | *dest, 0xba); +ROP3_HANDLERS(SPDSanax, (~(*src & *dest) & *pat) ^ *src, 0xbc); +ROP3_HANDLERS(SDxPDxan, ~((*dest ^ *pat) & (*dest ^ *src)), 0xbd); +ROP3_HANDLERS(DPSxo, (*src ^ *pat) | *dest, 0xbe); +ROP3_HANDLERS(DPSano, ~(*src & *pat) | *dest, 0xbf); +ROP3_HANDLERS(SPDSnaoxn, ~(((~*src & *dest) | *pat) ^ *src), 0xc1); +ROP3_HANDLERS(SPDSonoxn, ~((~(*src | *dest) | *pat) ^ *src), 0xc2); +ROP3_HANDLERS(SPDnoa, (~*dest | *pat) & *src, 0xc4); +ROP3_HANDLERS(SPDSxoxn, ~(((*src ^ *dest) | *pat) ^ *src), 0xc5); +ROP3_HANDLERS(SDPnax, (~*pat & *dest) ^ *src, 0xc6); +ROP3_HANDLERS(PSDPoaxn, ~(((*pat | *dest) & *src) ^ *pat), 0xc7); +ROP3_HANDLERS(SDPoa, (*pat | *dest) & *src, 0xc8); +ROP3_HANDLERS(SPDoxn, ~((*dest | *pat) ^ *src), 0xc9); +ROP3_HANDLERS(DPSDxax, ((*dest ^ *src) & *pat) ^ *dest, 0xca); +ROP3_HANDLERS(SPDSaoxn, ~(((*src & *dest) | *pat) ^ *src), 0xcb); +ROP3_HANDLERS(SDPono, ~(*pat | *dest) | *src, 0xcd); +ROP3_HANDLERS(SDPnao, (~*pat & *dest) | *src, 0xce); +ROP3_HANDLERS(PSDnoa, (~*dest | *src) & *pat, 0xd0); +ROP3_HANDLERS(PSDPxoxn, ~(((*pat ^ *dest) | *src) ^ *pat), 0xd1); +ROP3_HANDLERS(PDSnax, (~*src & *dest) ^ *pat, 0xd2); +ROP3_HANDLERS(SPDSoaxn, ~(((*src | *dest) & *pat) ^ *src), 0xd3); +ROP3_HANDLERS(SSPxPDxax, ((*dest ^ *pat) & (*pat ^ *src)) ^ *src, 0xd4); +ROP3_HANDLERS(DPSanan, ~(~(*src & *pat) & *dest), 0xd5); +ROP3_HANDLERS(PSDPSaoxx, ((*src & *pat) | *dest) ^ *src ^ *pat, 0xd6); +ROP3_HANDLERS(DPSxan, ~((*src ^ *pat) & *dest), 0xd7); +ROP3_HANDLERS(PDSPxax, ((*pat ^ *src) & *dest) ^ *pat, 0xd8); +ROP3_HANDLERS(SDPSaoxn, ~(((*src & *pat) | *dest) ^ *src), 0xd9); +ROP3_HANDLERS(DPSDanax, (~(*dest & *src) & *pat) ^ *dest, 0xda); +ROP3_HANDLERS(SPxDSxan, ~((*src ^ *dest) & (*pat ^ *src)), 0xdb); +ROP3_HANDLERS(SPDnao, (~*dest & *pat) | *src, 0xdc); +ROP3_HANDLERS(SDPxo, (*pat ^ *dest) | *src, 0xde); +ROP3_HANDLERS(SDPano, ~(*pat & *dest) | *src, 0xdf); +ROP3_HANDLERS(PDSoa, (*src | *dest) & *pat, 0xe0); +ROP3_HANDLERS(PDSoxn, ~((*src | *dest) ^ *pat), 0xe1); +ROP3_HANDLERS(DSPDxax, ((*dest ^ *pat) & *src) ^ *dest, 0xe2); +ROP3_HANDLERS(PSDPaoxn, ~(((*pat & *dest) | *src) ^ *pat), 0xe3); +ROP3_HANDLERS(SDPSxax, ((*src ^ *pat) & *dest) ^ *src, 0xe4); +ROP3_HANDLERS(PDSPaoxn, ~(((*pat & *src) | *dest) ^ *pat), 0xe5); +ROP3_HANDLERS(SDPSanax, (~(*src & *pat) & *dest) ^ *src, 0xe6); +ROP3_HANDLERS(SPxPDxan, ~((*dest ^ *pat) & (*pat ^ *src)), 0xe7); +ROP3_HANDLERS(SSPxDSxax, ((*src ^ *dest) & (*pat ^ *src)) ^ *src, 0xe8); +ROP3_HANDLERS(DSPDSanaxxn, ~((~(*src & *dest) & *pat) ^ *src ^ *dest), 0xe9); +ROP3_HANDLERS(DPSao, (*src & *pat) | *dest, 0xea); +ROP3_HANDLERS(DPSxno, ~(*src ^ *pat) | *dest, 0xeb); +ROP3_HANDLERS(SDPao, (*pat & *dest) | *src, 0xec); +ROP3_HANDLERS(SDPxno, ~(*pat ^ *dest) | *src, 0xed); +ROP3_HANDLERS(SDPnoo, ~*pat | *dest | *src, 0xef); +ROP3_HANDLERS(PDSono, ~(*src | *dest) | *pat, 0xf1); +ROP3_HANDLERS(PDSnao, (~*src & *dest) | *pat, 0xf2); +ROP3_HANDLERS(PSDnao, (~*dest & *src) | *pat, 0xf4); +ROP3_HANDLERS(PDSxo, (*src ^ *dest) | *pat, 0xf6); +ROP3_HANDLERS(PDSano, ~(*src & *dest) | *pat, 0xf7); +ROP3_HANDLERS(PDSao, (*src & *dest) | *pat, 0xf8); +ROP3_HANDLERS(PDSxno, ~(*src ^ *dest) | *pat, 0xf9); +ROP3_HANDLERS(DPSnoo, ~*src | *pat | *dest, 0xfb); +ROP3_HANDLERS(PSDnoo, ~*dest | *src | *pat, 0xfd); +ROP3_HANDLERS(DPSoo, *src | *pat | *dest, 0xfe); + + +#define ROP3_FILL_HANDLERS(op, index) \ + rop3_with_pattern_handlers_32[index] = rop3_handle_p32_##op; \ + rop3_with_pattern_handlers_16[index] = rop3_handle_p16_##op; \ + rop3_with_color_handlers_32[index] = rop3_handle_c32_##op; \ + rop3_with_color_handlers_16[index] = rop3_handle_c16_##op; \ + rop3_test_handlers_32[index] = rop3_test32_##op; \ + rop3_test_handlers_16[index] = rop3_test16_##op; + +SPICE_CONSTRUCTOR_FUNC(rop3_global_init) +{ + int i; + + for (i = 0; i < ROP3_NUM_OPS; i++) { + rop3_with_pattern_handlers_32[i] = default_rop3_with_pattern_handler; + rop3_with_pattern_handlers_16[i] = default_rop3_with_pattern_handler; + rop3_with_color_handlers_32[i] = default_rop3_withe_color_handler; + rop3_with_color_handlers_16[i] = default_rop3_withe_color_handler; + rop3_test_handlers_32[i] = default_rop3_test_handler; + rop3_test_handlers_16[i] = default_rop3_test_handler; + } + + ROP3_FILL_HANDLERS(DPSoon, 0x01); + ROP3_FILL_HANDLERS(DPSona, 0x02); + ROP3_FILL_HANDLERS(SDPona, 0x04); + ROP3_FILL_HANDLERS(PDSxnon, 0x06); + ROP3_FILL_HANDLERS(PDSaon, 0x07); + ROP3_FILL_HANDLERS(SDPnaa, 0x08); + ROP3_FILL_HANDLERS(PDSxon, 0x09); + ROP3_FILL_HANDLERS(PSDnaon, 0x0b); + ROP3_FILL_HANDLERS(PDSnaon, 0x0d); + ROP3_FILL_HANDLERS(PDSonon, 0x0e); + ROP3_FILL_HANDLERS(PDSona, 0x10); + ROP3_FILL_HANDLERS(SDPxnon, 0x12); + ROP3_FILL_HANDLERS(SDPaon, 0x13); + ROP3_FILL_HANDLERS(DPSxnon, 0x14); + ROP3_FILL_HANDLERS(DPSaon, 0x15); + ROP3_FILL_HANDLERS(PSDPSanaxx, 0x16); + ROP3_FILL_HANDLERS(SSPxDSxaxn, 0x17); + ROP3_FILL_HANDLERS(SPxPDxa, 0x18); + ROP3_FILL_HANDLERS(SDPSanaxn, 0x19); + ROP3_FILL_HANDLERS(PDSPaox, 0x1a); + ROP3_FILL_HANDLERS(SDPSxaxn, 0x1b); + ROP3_FILL_HANDLERS(PSDPaox, 0x1c); + ROP3_FILL_HANDLERS(DSPDxaxn, 0x1d); + ROP3_FILL_HANDLERS(PDSox, 0x1e); + ROP3_FILL_HANDLERS(PDSoan, 0x1f); + ROP3_FILL_HANDLERS(DPSnaa, 0x20); + ROP3_FILL_HANDLERS(SDPxon, 0x21); + ROP3_FILL_HANDLERS(SPDnaon, 0x23); + ROP3_FILL_HANDLERS(SPxDSxa, 0x24); + ROP3_FILL_HANDLERS(PDSPanaxn, 0x25); + ROP3_FILL_HANDLERS(SDPSaox, 0x26); + ROP3_FILL_HANDLERS(SDPSxnox, 0x27); + ROP3_FILL_HANDLERS(DPSxa, 0x28); + ROP3_FILL_HANDLERS(PSDPSaoxxn, 0x29); + ROP3_FILL_HANDLERS(DPSana, 0x2a); + ROP3_FILL_HANDLERS(SSPxPDxaxn, 0x2b); + ROP3_FILL_HANDLERS(SPDSoax, 0x2c); + ROP3_FILL_HANDLERS(PSDnox, 0x2d); + ROP3_FILL_HANDLERS(PSDPxox, 0x2e); + ROP3_FILL_HANDLERS(PSDnoan, 0x2f); + ROP3_FILL_HANDLERS(SDPnaon, 0x31); + ROP3_FILL_HANDLERS(SDPSoox, 0x32); + ROP3_FILL_HANDLERS(SPDSaox, 0x34); + ROP3_FILL_HANDLERS(SPDSxnox, 0x35); + ROP3_FILL_HANDLERS(SDPox, 0x36); + ROP3_FILL_HANDLERS(SDPoan, 0x37); + ROP3_FILL_HANDLERS(PSDPoax, 0x38); + ROP3_FILL_HANDLERS(SPDnox, 0x39); + ROP3_FILL_HANDLERS(SPDSxox, 0x3a); + ROP3_FILL_HANDLERS(SPDnoan, 0x3b); + ROP3_FILL_HANDLERS(SPDSonox, 0x3d); + ROP3_FILL_HANDLERS(SPDSnaox, 0x3e); + ROP3_FILL_HANDLERS(PSDnaa, 0x40); + ROP3_FILL_HANDLERS(DPSxon, 0x41); + ROP3_FILL_HANDLERS(SDxPDxa, 0x42); + ROP3_FILL_HANDLERS(SPDSanaxn, 0x43); + ROP3_FILL_HANDLERS(DPSnaon, 0x45); + ROP3_FILL_HANDLERS(DSPDaox, 0x46); + ROP3_FILL_HANDLERS(PSDPxaxn, 0x47); + ROP3_FILL_HANDLERS(SDPxa, 0x48); + ROP3_FILL_HANDLERS(PDSPDaoxxn, 0x49); + ROP3_FILL_HANDLERS(DPSDoax, 0x4a); + ROP3_FILL_HANDLERS(PDSnox, 0x4b); + ROP3_FILL_HANDLERS(SDPana, 0x4c); + ROP3_FILL_HANDLERS(SSPxDSxoxn, 0x4d); + ROP3_FILL_HANDLERS(PDSPxox, 0x4e); + ROP3_FILL_HANDLERS(PDSnoan, 0x4f); + ROP3_FILL_HANDLERS(DSPnaon, 0x51); + ROP3_FILL_HANDLERS(DPSDaox, 0x52); + ROP3_FILL_HANDLERS(SPDSxaxn, 0x53); + ROP3_FILL_HANDLERS(DPSonon, 0x54); + ROP3_FILL_HANDLERS(DPSox, 0x56); + ROP3_FILL_HANDLERS(DPSoan, 0x57); + ROP3_FILL_HANDLERS(PDSPoax, 0x58); + ROP3_FILL_HANDLERS(DPSnox, 0x59); + ROP3_FILL_HANDLERS(DPSDonox, 0x5b); + ROP3_FILL_HANDLERS(DPSDxox, 0x5c); + ROP3_FILL_HANDLERS(DPSnoan, 0x5d); + ROP3_FILL_HANDLERS(DPSDnaox, 0x5e); + ROP3_FILL_HANDLERS(PDSxa, 0x60); + ROP3_FILL_HANDLERS(DSPDSaoxxn, 0x61); + ROP3_FILL_HANDLERS(DSPDoax, 0x62); + ROP3_FILL_HANDLERS(SDPnox, 0x63); + ROP3_FILL_HANDLERS(SDPSoax, 0x64); + ROP3_FILL_HANDLERS(DSPnox, 0x65); + ROP3_FILL_HANDLERS(SDPSonox, 0x67); + ROP3_FILL_HANDLERS(DSPDSonoxxn, 0x68); + ROP3_FILL_HANDLERS(PDSxxn, 0x69); + ROP3_FILL_HANDLERS(DPSax, 0x6a); + ROP3_FILL_HANDLERS(PSDPSoaxxn, 0x6b); + ROP3_FILL_HANDLERS(SDPax, 0x6c); + ROP3_FILL_HANDLERS(PDSPDoaxxn, 0x6d); + ROP3_FILL_HANDLERS(SDPSnoax, 0x6e); + ROP3_FILL_HANDLERS(PDSxnan, 0x6f); + ROP3_FILL_HANDLERS(PDSana, 0x70); + ROP3_FILL_HANDLERS(SSDxPDxaxn, 0x71); + ROP3_FILL_HANDLERS(SDPSxox, 0x72); + ROP3_FILL_HANDLERS(SDPnoan, 0x73); + ROP3_FILL_HANDLERS(DSPDxox, 0x74); + ROP3_FILL_HANDLERS(DSPnoan, 0x75); + ROP3_FILL_HANDLERS(SDPSnaox, 0x76); + ROP3_FILL_HANDLERS(PDSax, 0x78); + ROP3_FILL_HANDLERS(DSPDSoaxxn, 0x79); + ROP3_FILL_HANDLERS(DPSDnoax, 0x7a); + ROP3_FILL_HANDLERS(SDPxnan, 0x7b); + ROP3_FILL_HANDLERS(SPDSnoax, 0x7c); + ROP3_FILL_HANDLERS(DPSxnan, 0x7d); + ROP3_FILL_HANDLERS(SPxDSxo, 0x7e); + ROP3_FILL_HANDLERS(DPSaan, 0x7f); + ROP3_FILL_HANDLERS(DPSaa, 0x80); + ROP3_FILL_HANDLERS(SPxDSxon, 0x81); + ROP3_FILL_HANDLERS(DPSxna, 0x82); + ROP3_FILL_HANDLERS(SPDSnoaxn, 0x83); + ROP3_FILL_HANDLERS(SDPxna, 0x84); + ROP3_FILL_HANDLERS(PDSPnoaxn, 0x85); + ROP3_FILL_HANDLERS(DSPDSoaxx, 0x86); + ROP3_FILL_HANDLERS(PDSaxn, 0x87); + ROP3_FILL_HANDLERS(SDPSnaoxn, 0x89); + ROP3_FILL_HANDLERS(DSPnoa, 0x8a); + ROP3_FILL_HANDLERS(DSPDxoxn, 0x8b); + ROP3_FILL_HANDLERS(SDPnoa, 0x8c); + ROP3_FILL_HANDLERS(SDPSxoxn, 0x8d); + ROP3_FILL_HANDLERS(SSDxPDxax, 0x8e); + ROP3_FILL_HANDLERS(PDSanan, 0x8f); + ROP3_FILL_HANDLERS(PDSxna, 0x90); + ROP3_FILL_HANDLERS(SDPSnoaxn, 0x91); + ROP3_FILL_HANDLERS(DPSDPoaxx, 0x92); + ROP3_FILL_HANDLERS(SPDaxn, 0x93); + ROP3_FILL_HANDLERS(PSDPSoaxx, 0x94); + ROP3_FILL_HANDLERS(DPSaxn, 0x95); + ROP3_FILL_HANDLERS(DPSxx, 0x96); + ROP3_FILL_HANDLERS(PSDPSonoxx, 0x97); + ROP3_FILL_HANDLERS(SDPSonoxn, 0x98); + ROP3_FILL_HANDLERS(DPSnax, 0x9a); + ROP3_FILL_HANDLERS(SDPSoaxn, 0x9b); + ROP3_FILL_HANDLERS(SPDnax, 0x9c); + ROP3_FILL_HANDLERS(DSPDoaxn, 0x9d); + ROP3_FILL_HANDLERS(DSPDSaoxx, 0x9e); + ROP3_FILL_HANDLERS(PDSxan, 0x9f); + ROP3_FILL_HANDLERS(PDSPnaoxn, 0xa1); + ROP3_FILL_HANDLERS(DPSnoa, 0xa2); + ROP3_FILL_HANDLERS(DPSDxoxn, 0xa3); + ROP3_FILL_HANDLERS(PDSPonoxn, 0xa4); + ROP3_FILL_HANDLERS(DSPnax, 0xa6); + ROP3_FILL_HANDLERS(PDSPoaxn, 0xa7); + ROP3_FILL_HANDLERS(DPSoa, 0xa8); + ROP3_FILL_HANDLERS(DPSoxn, 0xa9); + ROP3_FILL_HANDLERS(DPSono, 0xab); + ROP3_FILL_HANDLERS(SPDSxax, 0xac); + ROP3_FILL_HANDLERS(DPSDaoxn, 0xad); + ROP3_FILL_HANDLERS(DSPnao, 0xae); + ROP3_FILL_HANDLERS(PDSnoa, 0xb0); + ROP3_FILL_HANDLERS(PDSPxoxn, 0xb1); + ROP3_FILL_HANDLERS(SSPxDSxox, 0xb2); + ROP3_FILL_HANDLERS(SDPanan, 0xb3); + ROP3_FILL_HANDLERS(PSDnax, 0xb4); + ROP3_FILL_HANDLERS(DPSDoaxn, 0xb5); + ROP3_FILL_HANDLERS(DPSDPaoxx, 0xb6); + ROP3_FILL_HANDLERS(SDPxan, 0xb7); + ROP3_FILL_HANDLERS(PSDPxax, 0xb8); + ROP3_FILL_HANDLERS(DSPDaoxn, 0xb9); + ROP3_FILL_HANDLERS(DPSnao, 0xba); + ROP3_FILL_HANDLERS(SPDSanax, 0xbc); + ROP3_FILL_HANDLERS(SDxPDxan, 0xbd); + ROP3_FILL_HANDLERS(DPSxo, 0xbe); + ROP3_FILL_HANDLERS(DPSano, 0xbf); + ROP3_FILL_HANDLERS(SPDSnaoxn, 0xc1); + ROP3_FILL_HANDLERS(SPDSonoxn, 0xc2); + ROP3_FILL_HANDLERS(SPDnoa, 0xc4); + ROP3_FILL_HANDLERS(SPDSxoxn, 0xc5); + ROP3_FILL_HANDLERS(SDPnax, 0xc6); + ROP3_FILL_HANDLERS(PSDPoaxn, 0xc7); + ROP3_FILL_HANDLERS(SDPoa, 0xc8); + ROP3_FILL_HANDLERS(SPDoxn, 0xc9); + ROP3_FILL_HANDLERS(DPSDxax, 0xca); + ROP3_FILL_HANDLERS(SPDSaoxn, 0xcb); + ROP3_FILL_HANDLERS(SDPono, 0xcd); + ROP3_FILL_HANDLERS(SDPnao, 0xce); + ROP3_FILL_HANDLERS(PSDnoa, 0xd0); + ROP3_FILL_HANDLERS(PSDPxoxn, 0xd1); + ROP3_FILL_HANDLERS(PDSnax, 0xd2); + ROP3_FILL_HANDLERS(SPDSoaxn, 0xd3); + ROP3_FILL_HANDLERS(SSPxPDxax, 0xd4); + ROP3_FILL_HANDLERS(DPSanan, 0xd5); + ROP3_FILL_HANDLERS(PSDPSaoxx, 0xd6); + ROP3_FILL_HANDLERS(DPSxan, 0xd7); + ROP3_FILL_HANDLERS(PDSPxax, 0xd8); + ROP3_FILL_HANDLERS(SDPSaoxn, 0xd9); + ROP3_FILL_HANDLERS(DPSDanax, 0xda); + ROP3_FILL_HANDLERS(SPxDSxan, 0xdb); + ROP3_FILL_HANDLERS(SPDnao, 0xdc); + ROP3_FILL_HANDLERS(SDPxo, 0xde); + ROP3_FILL_HANDLERS(SDPano, 0xdf); + ROP3_FILL_HANDLERS(PDSoa, 0xe0); + ROP3_FILL_HANDLERS(PDSoxn, 0xe1); + ROP3_FILL_HANDLERS(DSPDxax, 0xe2); + ROP3_FILL_HANDLERS(PSDPaoxn, 0xe3); + ROP3_FILL_HANDLERS(SDPSxax, 0xe4); + ROP3_FILL_HANDLERS(PDSPaoxn, 0xe5); + ROP3_FILL_HANDLERS(SDPSanax, 0xe6); + ROP3_FILL_HANDLERS(SPxPDxan, 0xe7); + ROP3_FILL_HANDLERS(SSPxDSxax, 0xe8); + ROP3_FILL_HANDLERS(DSPDSanaxxn, 0xe9); + ROP3_FILL_HANDLERS(DPSao, 0xea); + ROP3_FILL_HANDLERS(DPSxno, 0xeb); + ROP3_FILL_HANDLERS(SDPao, 0xec); + ROP3_FILL_HANDLERS(SDPxno, 0xed); + ROP3_FILL_HANDLERS(SDPnoo, 0xef); + ROP3_FILL_HANDLERS(PDSono, 0xf1); + ROP3_FILL_HANDLERS(PDSnao, 0xf2); + ROP3_FILL_HANDLERS(PSDnao, 0xf4); + ROP3_FILL_HANDLERS(PDSxo, 0xf6); + ROP3_FILL_HANDLERS(PDSano, 0xf7); + ROP3_FILL_HANDLERS(PDSao, 0xf8); + ROP3_FILL_HANDLERS(PDSxno, 0xf9); + ROP3_FILL_HANDLERS(DPSnoo, 0xfb); + ROP3_FILL_HANDLERS(PSDnoo, 0xfd); + ROP3_FILL_HANDLERS(DPSoo, 0xfe); + + for (i = 0; i < ROP3_NUM_OPS; i++) { + rop3_test_handlers_32[i](); + rop3_test_handlers_16[i](); + } +} + +void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, + pixman_image_t *p, SpicePoint *pat_pos) +{ + int bpp; + + bpp = spice_pixman_image_get_bpp(d); + spice_assert(bpp == spice_pixman_image_get_bpp(s)); + spice_assert(bpp == spice_pixman_image_get_bpp(p)); + + if (bpp == 32) { + rop3_with_pattern_handlers_32[rop3](d, s, src_pos, p, pat_pos); + } else { + rop3_with_pattern_handlers_16[rop3](d, s, src_pos, p, pat_pos); + } +} + +void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, + uint32_t rgb) +{ + int bpp; + + bpp = spice_pixman_image_get_bpp(d); + spice_assert(bpp == spice_pixman_image_get_bpp(s)); + + if (bpp == 32) { + rop3_with_color_handlers_32[rop3](d, s, src_pos, rgb); + } else { + rop3_with_color_handlers_16[rop3](d, s, src_pos, rgb); + } +} diff --git a/spice-common/common/rop3.h b/spice-common/common/rop3.h new file mode 100644 index 0000000..20e100c --- /dev/null +++ b/spice-common/common/rop3.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_ROP3 +#define _H_ROP3 + +#include +#include + +#include "draw.h" +#include "pixman_utils.h" + +SPICE_BEGIN_DECLS + +void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, + pixman_image_t *p, SpicePoint *pat_pos); +void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, + uint32_t rgb); + +static inline SPICE_GNUC_DEPRECATED void rop3_init(void) {} + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/snd_codec.c b/spice-common/common/snd_codec.c new file mode 100644 index 0000000..9738311 --- /dev/null +++ b/spice-common/common/snd_codec.c @@ -0,0 +1,400 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Jeremy White + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +/* snd_codec.c + General purpose sound codec routines for use by Spice. + These routines abstract the work of picking a codec and + encoding and decoding the buffers. + Note: these routines have some peculiarities that come from + wanting to provide full backwards compatibility with the original + Spice celt 0.51 implementation. It has some hard requirements + (fixed sample size, fixed compressed buffer size). + + See below for documentation of the public routines. +*/ + +#include "config.h" +#include +#include +#include +#include + + +#include "snd_codec.h" +#include "mem.h" +#include "log.h" + +typedef struct +{ + int mode; + int frequency; +#if HAVE_CELT051 + CELTMode *celt_mode; + CELTEncoder *celt_encoder; + CELTDecoder *celt_decoder; +#endif + +#if HAVE_OPUS + OpusEncoder *opus_encoder; + OpusDecoder *opus_decoder; +#endif +} SndCodecInternal; + + + +/* celt 0.51 specific support routines */ +#if HAVE_CELT051 +static void snd_codec_destroy_celt051(SndCodecInternal *codec) +{ + if (codec->celt_decoder) { + celt051_decoder_destroy(codec->celt_decoder); + codec->celt_decoder = NULL; + } + + if (codec->celt_encoder) { + celt051_encoder_destroy(codec->celt_encoder); + codec->celt_encoder = NULL; + } + + if (codec->celt_mode) { + celt051_mode_destroy(codec->celt_mode); + codec->celt_mode = NULL; + } +} + +static int snd_codec_create_celt051(SndCodecInternal *codec, int purpose) +{ + int celt_error; + + codec->celt_mode = celt051_mode_create(codec->frequency, + SND_CODEC_PLAYBACK_CHAN, + SND_CODEC_CELT_FRAME_SIZE, &celt_error); + if (! codec->celt_mode) { + spice_printerr("create celt mode failed %d", celt_error); + return SND_CODEC_UNAVAILABLE; + } + + if (purpose & SND_CODEC_ENCODE) { + codec->celt_encoder = celt051_encoder_create(codec->celt_mode); + if (! codec->celt_encoder) { + spice_printerr("create celt encoder failed"); + goto error; + } + } + + if (purpose & SND_CODEC_DECODE) { + codec->celt_decoder = celt051_decoder_create(codec->celt_mode); + if (! codec->celt_decoder) { + spice_printerr("create celt decoder failed"); + goto error; + } + } + + codec->mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1; + return SND_CODEC_OK; + +error: + snd_codec_destroy_celt051(codec); + return SND_CODEC_UNAVAILABLE; +} + +static int snd_codec_encode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ + int n; + if (in_size != SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2) + return SND_CODEC_INVALID_ENCODE_SIZE; + n = celt051_encode(codec->celt_encoder, (celt_int16_t *) in_ptr, NULL, out_ptr, *out_size); + if (n < 0) { + spice_printerr("celt051_encode failed %d\n", n); + return SND_CODEC_ENCODE_FAILED; + } + *out_size = n; + return SND_CODEC_OK; +} + +static int snd_codec_decode_celt051(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ + int n; + n = celt051_decode(codec->celt_decoder, in_ptr, in_size, (celt_int16_t *) out_ptr); + if (n < 0) { + spice_printerr("celt051_decode failed %d\n", n); + return SND_CODEC_DECODE_FAILED; + } + *out_size = SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2 /* 16 fmt */; + return SND_CODEC_OK; +} +#endif + + +/* Opus support routines */ +#if HAVE_OPUS +static void snd_codec_destroy_opus(SndCodecInternal *codec) +{ + if (codec->opus_decoder) { + opus_decoder_destroy(codec->opus_decoder); + codec->opus_decoder = NULL; + } + + if (codec->opus_encoder) { + opus_encoder_destroy(codec->opus_encoder); + codec->opus_encoder = NULL; + } + +} + +static int snd_codec_create_opus(SndCodecInternal *codec, int purpose) +{ + int opus_error; + + if (purpose & SND_CODEC_ENCODE) { + codec->opus_encoder = opus_encoder_create(codec->frequency, + SND_CODEC_PLAYBACK_CHAN, + OPUS_APPLICATION_AUDIO, &opus_error); + if (! codec->opus_encoder) { + spice_printerr("create opus encoder failed; error %d", opus_error); + goto error; + } + } + + if (purpose & SND_CODEC_DECODE) { + codec->opus_decoder = opus_decoder_create(codec->frequency, + SND_CODEC_PLAYBACK_CHAN, &opus_error); + if (! codec->opus_decoder) { + spice_printerr("create opus decoder failed; error %d", opus_error); + goto error; + } + } + + codec->mode = SPICE_AUDIO_DATA_MODE_OPUS; + return SND_CODEC_OK; + +error: + snd_codec_destroy_opus(codec); + return SND_CODEC_UNAVAILABLE; +} + +static int snd_codec_encode_opus(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ + int n; + if (in_size != SND_CODEC_OPUS_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2) + return SND_CODEC_INVALID_ENCODE_SIZE; + n = opus_encode(codec->opus_encoder, (opus_int16 *) in_ptr, SND_CODEC_OPUS_FRAME_SIZE, out_ptr, *out_size); + if (n < 0) { + spice_printerr("opus_encode failed %d\n", n); + return SND_CODEC_ENCODE_FAILED; + } + *out_size = n; + return SND_CODEC_OK; +} + +static int snd_codec_decode_opus(SndCodecInternal *codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ + int n; + n = opus_decode(codec->opus_decoder, in_ptr, in_size, (opus_int16 *) out_ptr, + *out_size / SND_CODEC_PLAYBACK_CHAN / 2, 0); + if (n < 0) { + spice_printerr("opus_decode failed %d\n", n); + return SND_CODEC_DECODE_FAILED; + } + *out_size = n * SND_CODEC_PLAYBACK_CHAN * 2 /* 16 fmt */; + return SND_CODEC_OK; +} +#endif + + +/*---------------------------------------------------------------------------- +** PUBLIC INTERFACE +**--------------------------------------------------------------------------*/ + +/* + snd_codec_is_capable + Returns TRUE if the current spice implementation can + use the given codec, FALSE otherwise. + mode must be a SPICE_AUDIO_DATA_MODE_XXX enum from spice/enum.h + */ +int snd_codec_is_capable(int mode, int frequency) +{ +#if HAVE_CELT051 + if (mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) + return TRUE; +#endif + +#if HAVE_OPUS + if (mode == SPICE_AUDIO_DATA_MODE_OPUS && + (frequency == SND_CODEC_ANY_FREQUENCY || + frequency == 48000 || frequency == 24000 || + frequency == 16000 || frequency == 12000 || + frequency == 8000) ) + return TRUE; +#endif + + return FALSE; +} + +/* + snd_codec_create + Create a codec control. Required for most functions in this library. + Parameters: + 1. codec Pointer to preallocated codec control + 2. mode SPICE_AUDIO_DATA_MODE_XXX enum from spice/enum.h + 3. encode TRUE if encoding is desired + 4. decode TRUE if decoding is desired + Returns: + SND_CODEC_OK if all went well; a different code if not. + + snd_codec_destroy is the obvious partner of snd_codec_create. + */ +int snd_codec_create(SndCodec *codec, int mode, int frequency, int purpose) +{ + int rc = SND_CODEC_UNAVAILABLE; + SndCodecInternal **c = (SndCodecInternal **) codec; + + *c = spice_new0(SndCodecInternal, 1); + (*c)->frequency = frequency; + +#if HAVE_CELT051 + if (mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) + rc = snd_codec_create_celt051(*c, purpose); +#endif + +#if HAVE_OPUS + if (mode == SPICE_AUDIO_DATA_MODE_OPUS) + rc = snd_codec_create_opus(*c, purpose); +#endif + + return rc; +} + +/* + snd_codec_destroy + The obvious companion to snd_codec_create +*/ +void snd_codec_destroy(SndCodec *codec) +{ + SndCodecInternal **c = (SndCodecInternal **) codec; + if (! c || ! *c) + return; + +#if HAVE_CELT051 + snd_codec_destroy_celt051(*c); +#endif + +#if HAVE_OPUS + snd_codec_destroy_opus(*c); +#endif + + free(*c); + *c = NULL; +} + +/* + snd_codec_frame_size + Returns the size, in frames, of the raw PCM frame buffer + required by this codec. To get bytes, you'll need + to multiply by channels and sample width. + */ +int snd_codec_frame_size(SndCodec codec) +{ +#if defined(HAVE_CELT051) || defined(HAVE_OPUS) + SndCodecInternal *c = (SndCodecInternal *) codec; +#endif +#if HAVE_CELT051 + if (c && c->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) + return SND_CODEC_CELT_FRAME_SIZE; +#endif +#if HAVE_OPUS + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) + return SND_CODEC_OPUS_FRAME_SIZE; +#endif + return SND_CODEC_MAX_FRAME_SIZE; +} + +/* + snd_codec_encode + Encode a block of data to a compressed buffer. + + Parameters: + 1. codec Pointer to codec control previously allocated + created + 2. in_data Pointer to uncompressed PCM data + 3. in_size Input size (for celt, this must be a + particular size, governed by the frame size) + 4. out_ptr Pointer to area to write encoded data + 5. out_size On input, the maximum size of the output buffer; on + successful return, it will hold the number of bytes + returned. For celt, this must be set to a particular + size to ensure compatibility. + + Returns: + SND_CODEC_OK if all went well +*/ +int snd_codec_encode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ +#if defined(HAVE_CELT051) || defined(HAVE_OPUS) + SndCodecInternal *c = (SndCodecInternal *) codec; +#endif +#if HAVE_CELT051 + if (c && c->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { + /* The output buffer size in celt determines the compression, + and so is essentially mandatory to use a certain value (47) */ + if (*out_size > SND_CODEC_CELT_COMPRESSED_FRAME_BYTES) + *out_size = SND_CODEC_CELT_COMPRESSED_FRAME_BYTES; + return snd_codec_encode_celt051(c, in_ptr, in_size, out_ptr, out_size); + } +#endif + +#if HAVE_OPUS + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) + return snd_codec_encode_opus(c, in_ptr, in_size, out_ptr, out_size); +#endif + + return SND_CODEC_ENCODER_UNAVAILABLE; +} + +/* + snd_codec_decode + Decode a block of data from a compressed buffer. + + Parameters: + 1. codec Pointer to codec control previously allocated + created + 2. in_data Pointer to compressed data + 3. in_size Input size + 4. out_ptr Pointer to area to write decoded data + 5. out_size On input, the maximum size of the output buffer; on + successful return, it will hold the number of bytes + returned. + + Returns: + SND_CODEC_OK if all went well +*/ +int snd_codec_decode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size) +{ +#if defined(HAVE_CELT051) || defined(HAVE_OPUS) + SndCodecInternal *c = (SndCodecInternal *) codec; +#endif +#if HAVE_CELT051 + if (c && c->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) + return snd_codec_decode_celt051(c, in_ptr, in_size, out_ptr, out_size); +#endif + +#if HAVE_OPUS + if (c && c->mode == SPICE_AUDIO_DATA_MODE_OPUS) + return snd_codec_decode_opus(c, in_ptr, in_size, out_ptr, out_size); +#endif + + return SND_CODEC_DECODER_UNAVAILABLE; +} diff --git a/spice-common/common/snd_codec.h b/spice-common/common/snd_codec.h new file mode 100644 index 0000000..e4122a4 --- /dev/null +++ b/spice-common/common/snd_codec.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Jeremy White + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H_SND_CODEC +#define _H_SND_CODEC + + +#if HAVE_CELT051 +#include +#endif + +#if HAVE_OPUS +#include +#endif + +/* Spice uses a very fixed protocol when transmitting CELT audio; + audio must be transmitted in frames of 256, and we must compress + data down to a fairly specific size (47, computation below). + While the protocol doesn't inherently specify this, the expectation + of older clients and server mandates it. +*/ +#define SND_CODEC_CELT_FRAME_SIZE 256 +#define SND_CODEC_CELT_BIT_RATE (64 * 1024) +#define SND_CODEC_CELT_PLAYBACK_FREQ 44100 +#define SND_CODEC_CELT_COMPRESSED_FRAME_BYTES (SND_CODEC_CELT_FRAME_SIZE * SND_CODEC_CELT_BIT_RATE / \ + SND_CODEC_CELT_PLAYBACK_FREQ / 8) + +#define SND_CODEC_OPUS_FRAME_SIZE 480 +#define SND_CODEC_OPUS_PLAYBACK_FREQ 48000 +#define SND_CODEC_OPUS_COMPRESSED_FRAME_BYTES 480 + +#define SND_CODEC_PLAYBACK_CHAN 2 + +#define SND_CODEC_MAX_FRAME_SIZE (MAX(SND_CODEC_CELT_FRAME_SIZE, SND_CODEC_OPUS_FRAME_SIZE)) +#define SND_CODEC_MAX_FRAME_BYTES (SND_CODEC_MAX_FRAME_SIZE * SND_CODEC_PLAYBACK_CHAN * 2 /* FMT_S16 */) +#define SND_CODEC_MAX_COMPRESSED_BYTES MAX(SND_CODEC_CELT_COMPRESSED_FRAME_BYTES, SND_CODEC_OPUS_COMPRESSED_FRAME_BYTES) + +#define SND_CODEC_ANY_FREQUENCY -1 + +#define SND_CODEC_OK 0 +#define SND_CODEC_UNAVAILABLE 1 +#define SND_CODEC_ENCODER_UNAVAILABLE 2 +#define SND_CODEC_DECODER_UNAVAILABLE 3 +#define SND_CODEC_ENCODE_FAILED 4 +#define SND_CODEC_DECODE_FAILED 5 +#define SND_CODEC_INVALID_ENCODE_SIZE 6 + +#define SND_CODEC_ENCODE 0x0001 +#define SND_CODEC_DECODE 0x0002 + +SPICE_BEGIN_DECLS + +typedef struct SndCodecInternal * SndCodec; + +int snd_codec_is_capable(int mode, int frequency); + +int snd_codec_create(SndCodec *codec, int mode, int frequency, int purpose); +void snd_codec_destroy(SndCodec *codec); + +int snd_codec_frame_size(SndCodec codec); + +int snd_codec_encode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size); +int snd_codec_decode(SndCodec codec, uint8_t *in_ptr, int in_size, uint8_t *out_ptr, int *out_size); + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/spice_common.h b/spice-common/common/spice_common.h new file mode 100644 index 0000000..5572326 --- /dev/null +++ b/spice-common/common/spice_common.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef H_SPICE_COMMON +#define H_SPICE_COMMON + +#include +#include +#include +#include +#include + +#include +#include "backtrace.h" +#include "log.h" + +#ifdef SPICE_DISABLE_ABORT +#define spice_abort() do { } while(0) +#else +#define spice_abort() abort() +#endif + +#endif diff --git a/spice-common/common/ssl_verify.c b/spice-common/common/ssl_verify.c new file mode 100644 index 0000000..601252e --- /dev/null +++ b/spice-common/common/ssl_verify.c @@ -0,0 +1,548 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "mem.h" +#include "ssl_verify.h" +#include "log.h" + +#ifndef WIN32 +#include +#include +#include +#endif +#include +#include +#include + +static int verify_pubkey(X509* cert, const char *key, size_t key_size) +{ + EVP_PKEY* cert_pubkey = NULL; + EVP_PKEY* orig_pubkey = NULL; + BIO* bio = NULL; + int ret = 0; + + if (!key || key_size == 0) + return 0; + + if (!cert) { + spice_debug("warning: no cert!"); + return 0; + } + + cert_pubkey = X509_get_pubkey(cert); + if (!cert_pubkey) { + spice_debug("warning: reading public key from certificate failed"); + goto finish; + } + + bio = BIO_new_mem_buf((void*)key, key_size); + if (!bio) { + spice_debug("creating BIO failed"); + goto finish; + } + + orig_pubkey = d2i_PUBKEY_bio(bio, NULL); + if (!orig_pubkey) { + spice_debug("reading pubkey from bio failed"); + goto finish; + } + + ret = EVP_PKEY_cmp(orig_pubkey, cert_pubkey); + + if (ret == 1) { + spice_debug("public keys match"); + } else if (ret == 0) { + spice_debug("public keys mismatch"); + } else { + spice_debug("public keys types mismatch"); + } + +finish: + if (bio) + BIO_free(bio); + + if (orig_pubkey) + EVP_PKEY_free(orig_pubkey); + + if (cert_pubkey) + EVP_PKEY_free(cert_pubkey); + + return ret; +} + +/* from gnutls + * compare hostname against certificate, taking account of wildcards + * return 1 on success or 0 on error + * + * note: certnamesize is required as X509 certs can contain embedded NULs in + * the strings such as CN or subjectAltName + */ +static int _gnutls_hostname_compare(const char *certname, + size_t certnamesize, const char *hostname) +{ + /* find the first different character */ + for (; *certname && *hostname && toupper (*certname) == toupper (*hostname); + certname++, hostname++, certnamesize--) + ; + + /* the strings are the same */ + if (certnamesize == 0 && *hostname == '\0') + return 1; + + if (*certname == '*') + { + /* a wildcard certificate */ + + certname++; + certnamesize--; + + while (1) + { + /* Use a recursive call to allow multiple wildcards */ + if (_gnutls_hostname_compare (certname, certnamesize, hostname)) + return 1; + + /* wildcards are only allowed to match a single domain + component or component fragment */ + if (*hostname == '\0' || *hostname == '.') + break; + hostname++; + } + + return 0; + } + + return 0; +} + +/** + * From gnutls and spice red_peer.c + * TODO: switch to gnutls and get rid of this + * + * This function will check if the given certificate's subject matches + * the given hostname. This is a basic implementation of the matching + * described in RFC2818 (HTTPS), which takes into account wildcards, + * and the DNSName/IPAddress subject alternative name PKIX extension. + * + * Returns: 1 for a successful match, and 0 on failure. + **/ +static int verify_hostname(X509* cert, const char *hostname) +{ + GENERAL_NAMES* subject_alt_names; + int found_dns_name = 0; + int cn_match = 0; + X509_NAME* subject; + + spice_return_val_if_fail(hostname != NULL, 0); + + if (!cert) { + spice_debug("warning: no cert!"); + return 0; + } + + /* try matching against: + * 1) a DNS name as an alternative name (subjectAltName) extension + * in the certificate + * 2) the common name (CN) in the certificate + * + * either of these may be of the form: *.domain.tld + * + * only try (2) if there is no subjectAltName extension of + * type dNSName + */ + + /* Check through all included subjectAltName extensions, comparing + * against all those of type dNSName. + */ + subject_alt_names = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + + if (subject_alt_names) { + int num_alts = sk_GENERAL_NAME_num(subject_alt_names); + int i; + for (i = 0; i < num_alts; i++) { + const GENERAL_NAME* name = sk_GENERAL_NAME_value(subject_alt_names, i); + if (name->type == GEN_DNS) { + found_dns_name = 1; + if (_gnutls_hostname_compare((char *)ASN1_STRING_data(name->d.dNSName), + ASN1_STRING_length(name->d.dNSName), + hostname)) { + spice_debug("alt name match=%s", ASN1_STRING_data(name->d.dNSName)); + GENERAL_NAMES_free(subject_alt_names); + return 1; + } + } else if (name->type == GEN_IPADD) { + GInetAddress * ip = NULL; + const guint8 * ip_binary = NULL; + int alt_ip_len = 0; + int ip_len = 0; + + found_dns_name = 1; + + ip = g_inet_address_new_from_string(hostname); + if (ip != NULL) { + ip_len = g_inet_address_get_native_size(ip); + ip_binary = g_inet_address_to_bytes(ip); + } else { + spice_warning("Could not parse hostname: %s", hostname); + } + + alt_ip_len = ASN1_STRING_length(name->d.iPAddress); + + if ((ip_len == alt_ip_len) && + (memcmp(ASN1_STRING_data(name->d.iPAddress), ip_binary, ip_len)) == 0) { + GInetAddress * alt_ip = NULL; + gchar * alt_ip_string = NULL; + + alt_ip = g_inet_address_new_from_bytes(ASN1_STRING_data(name->d.iPAddress), + g_inet_address_get_family(ip)); + alt_ip_string = g_inet_address_to_string(alt_ip); + spice_debug("alt name IP match=%s", alt_ip_string); + + g_free(alt_ip_string); + g_object_unref(alt_ip); + g_object_unref(ip); + GENERAL_NAMES_free(subject_alt_names); + return 1; + } + if (ip != NULL) { + g_object_unref(ip); + } + } + } + GENERAL_NAMES_free(subject_alt_names); + } + + if (found_dns_name) { + spice_debug("warning: SubjectAltName mismatch"); + return 0; + } + + /* extracting commonNames */ + subject = X509_get_subject_name(cert); + if (subject) { + int pos = -1; + X509_NAME_ENTRY* cn_entry; + ASN1_STRING* cn_asn1; + + while ((pos = X509_NAME_get_index_by_NID(subject, NID_commonName, pos)) != -1) { + cn_entry = X509_NAME_get_entry(subject, pos); + if (!cn_entry) { + continue; + } + cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); + if (!cn_asn1) { + continue; + } + + if (_gnutls_hostname_compare((char*)ASN1_STRING_data(cn_asn1), + ASN1_STRING_length(cn_asn1), + hostname)) { + spice_debug("common name match=%s", (char*)ASN1_STRING_data(cn_asn1)); + cn_match = 1; + break; + } + } + } + + if (!cn_match) { + spice_debug("warning: common name mismatch"); + } + + return cn_match; +} + +static X509_NAME* subject_to_x509_name(const char *subject, int *nentries) +{ + X509_NAME* in_subject; + const char *p; + char *key, *val, *k, *v = NULL; + enum { + KEY, + VALUE + } state; + + spice_return_val_if_fail(subject != NULL, NULL); + spice_return_val_if_fail(nentries != NULL, NULL); + + key = (char*)alloca(strlen(subject)); + val = (char*)alloca(strlen(subject)); + in_subject = X509_NAME_new(); + + if (!in_subject || !key || !val) { + spice_debug("failed to allocate"); + return NULL; + } + + *nentries = 0; + + k = key; + state = KEY; + for (p = subject;; ++p) { + int escape = 0; + if (*p == '\\') { + ++p; + if (*p != '\\' && *p != ',') { + spice_debug("Invalid character after \\"); + goto fail; + } + escape = 1; + } + + switch (state) { + case KEY: + if (*p == ' ' && k == key) { + continue; /* skip spaces before key */ + } if (*p == 0) { + if (k == key) /* empty key, ending */ + goto success; + goto fail; + } else if (*p == ',' && !escape) { + goto fail; /* assignment is missing */ + } else if (*p == '=' && !escape) { + state = VALUE; + *k = 0; + v = val; + } else + *k++ = *p; + break; + case VALUE: + if (*p == 0 || (*p == ',' && !escape)) { + if (v == val) /* empty value */ + goto fail; + + *v = 0; + + if (!X509_NAME_add_entry_by_txt(in_subject, key, + MBSTRING_UTF8, + (const unsigned char*)val, + -1, -1, 0)) { + spice_debug("warning: failed to add entry %s=%s to X509_NAME", + key, val); + goto fail; + } + *nentries += 1; + + if (*p == 0) + goto success; + + state = KEY; + k = key; + } else + *v++ = *p; + break; + } + } + +success: + return in_subject; + +fail: + if (in_subject) + X509_NAME_free(in_subject); + + return NULL; +} + +static int verify_subject(X509* cert, SpiceOpenSSLVerify* verify) +{ + X509_NAME *cert_subject = NULL; + X509_NAME* in_subject; + int ret; + int in_entries; + + if (!cert) { + spice_debug("warning: no cert!"); + return 0; + } + + cert_subject = X509_get_subject_name(cert); + if (!cert_subject) { + spice_debug("warning: reading certificate subject failed"); + return 0; + } + + in_subject = subject_to_x509_name(verify->subject, &in_entries); + if (!in_subject) { + spice_debug("warning: no in_subject!"); + return 0; + } + + /* Note: this check is redundant with the pre-condition in X509_NAME_cmp */ + if (X509_NAME_entry_count(cert_subject) != in_entries) { + spice_debug("subject mismatch: #entries cert=%d, input=%d", + X509_NAME_entry_count(cert_subject), in_entries); + X509_NAME_free(in_subject); + return 0; + } + + ret = X509_NAME_cmp(cert_subject, in_subject); + + if (ret == 0) { + spice_debug("subjects match"); + } else { + char *p; + spice_debug("subjects mismatch"); + + p = X509_NAME_oneline(cert_subject, NULL, 0); + spice_debug("cert_subject: %s", p); + free(p); + + p = X509_NAME_oneline(in_subject, NULL, 0); + spice_debug("in_subject: %s", p); + free(p); + } + X509_NAME_free(in_subject); + + return !ret; +} + +static int openssl_verify(int preverify_ok, X509_STORE_CTX *ctx) +{ + int depth, err; + SpiceOpenSSLVerify *v; + SSL *ssl; + X509* cert; + char buf[256]; + unsigned int failed_verifications; + + ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + v = (SpiceOpenSSLVerify*)SSL_get_app_data(ssl); + + cert = X509_STORE_CTX_get_current_cert(ctx); + X509_NAME_oneline(X509_get_subject_name(cert), buf, 256); + depth = X509_STORE_CTX_get_error_depth(ctx); + err = X509_STORE_CTX_get_error(ctx); + if (depth > 0) { + if (!preverify_ok) { + spice_warning("Error in certificate chain verification: %s (num=%d:depth%d:%s)", + X509_verify_cert_error_string(err), err, depth, buf); + v->all_preverify_ok = 0; + + /* if certificate verification failed, we can still authorize the server */ + /* if its public key matches the one we hold in the peer_connect_options. */ + if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN && + v->verifyop & SPICE_SSL_VERIFY_OP_PUBKEY) + return 1; + + if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) + spice_debug("server certificate not being signed by the provided CA"); + + return 0; + } else + return 1; + } + + /* depth == 0 */ + if (!cert) { + spice_debug("failed to get server certificate"); + return 0; + } + + failed_verifications = 0; + if (v->verifyop & SPICE_SSL_VERIFY_OP_PUBKEY) { + if (verify_pubkey(cert, v->pubkey, v->pubkey_size)) + return 1; + else + failed_verifications |= SPICE_SSL_VERIFY_OP_PUBKEY; + } + + if (!preverify_ok) { + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + spice_warning("Error in server certificate verification: %s (num=%d:depth%d:%s)", + X509_verify_cert_error_string(err), err, depth, buf); + return 0; + } + if (!v->all_preverify_ok) { + return 0; + } + + if (v->verifyop & SPICE_SSL_VERIFY_OP_SUBJECT) { + if (verify_subject(cert, v)) + return 1; + else + failed_verifications |= SPICE_SSL_VERIFY_OP_SUBJECT; + } else if (v->verifyop & SPICE_SSL_VERIFY_OP_HOSTNAME) { + if (verify_hostname(cert, v->hostname)) + return 1; + else + failed_verifications |= SPICE_SSL_VERIFY_OP_HOSTNAME; + } + + /* If we reach this code, this means all the tests failed, thus + * verification failed + */ + if (failed_verifications & SPICE_SSL_VERIFY_OP_PUBKEY) + spice_warning("ssl: pubkey verification failed"); + + if (failed_verifications & SPICE_SSL_VERIFY_OP_HOSTNAME) + spice_warning("ssl: hostname '%s' verification failed", v->hostname); + + if (failed_verifications & SPICE_SSL_VERIFY_OP_SUBJECT) + spice_warning("ssl: subject '%s' verification failed", v->subject); + + spice_warning("ssl: verification failed"); + + return 0; +} + +SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop, + const char *hostname, + const char *pubkey, size_t pubkey_size, + const char *subject) +{ + SpiceOpenSSLVerify *v; + + if (!verifyop) + return NULL; + + v = spice_new0(SpiceOpenSSLVerify, 1); + + v->ssl = ssl; + v->verifyop = verifyop; + v->hostname = spice_strdup(hostname); + v->pubkey = (char*)spice_memdup(pubkey, pubkey_size); + v->pubkey_size = pubkey_size; + v->subject = spice_strdup(subject); + + v->all_preverify_ok = 1; + + SSL_set_app_data(ssl, v); + SSL_set_verify(ssl, + SSL_VERIFY_PEER, openssl_verify); + + return v; +} + +void spice_openssl_verify_free(SpiceOpenSSLVerify* verify) +{ + if (!verify) + return; + + free(verify->pubkey); + free(verify->subject); + free(verify->hostname); + + if (verify->ssl) + SSL_set_app_data(verify->ssl, NULL); + free(verify); +} diff --git a/spice-common/common/ssl_verify.h b/spice-common/common/ssl_verify.h new file mode 100644 index 0000000..e32ca54 --- /dev/null +++ b/spice-common/common/ssl_verify.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef SSL_VERIFY_H +#define SSL_VERIFY_H + +#if defined(WIN32) +#include +#include +#ifdef X509_NAME +/* wincrypt.h has already a different define... */ +#undef X509_NAME +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#include + +SPICE_BEGIN_DECLS + +typedef enum { + SPICE_SSL_VERIFY_OP_NONE = 0, + SPICE_SSL_VERIFY_OP_PUBKEY = (1 << 0), + SPICE_SSL_VERIFY_OP_HOSTNAME = (1 << 1), + SPICE_SSL_VERIFY_OP_SUBJECT = (1 << 2), +} SPICE_SSL_VERIFY_OP; + +typedef struct { + SSL *ssl; + SPICE_SSL_VERIFY_OP verifyop; + int all_preverify_ok; + char *hostname; + char *pubkey; + size_t pubkey_size; + char *subject; +} SpiceOpenSSLVerify; + +SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop, + const char *hostname, + const char *pubkey, size_t pubkey_size, + const char *subject); +void spice_openssl_verify_free(SpiceOpenSSLVerify* verify); + +SPICE_END_DECLS + +#endif // SSL_VERIFY_H diff --git a/spice-common/common/sw_canvas.c b/spice-common/common/sw_canvas.c new file mode 100644 index 0000000..e8b0f3b --- /dev/null +++ b/spice-common/common/sw_canvas.c @@ -0,0 +1,1323 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#ifdef __MINGW32__ +#undef HAVE_STDLIB_H +#endif +#include +#endif + +#include +#include "sw_canvas.h" +#define CANVAS_USE_PIXMAN +#define CANVAS_SINGLE_INSTANCE +#include "canvas_base.c" +#include "rect.h" +#include "region.h" +#include "pixman_utils.h" + +typedef struct SwCanvas SwCanvas; + +struct SwCanvas { + CanvasBase base; + uint32_t *private_data; + int private_data_size; + pixman_image_t *image; +}; + +static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas, + SpiceBrush *brush) +{ + switch (brush->type) { + case SPICE_BRUSH_TYPE_SOLID: { + uint32_t color = brush->u.color; + pixman_color_t c; + + c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; + color >>= canvas->base.color_shift; + c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; + color >>= canvas->base.color_shift; + c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; + c.alpha = 0xffff; + + return pixman_image_create_solid_fill(&c); + } + case SPICE_BRUSH_TYPE_PATTERN: { + SwCanvas *surface_canvas; + pixman_image_t* surface; + pixman_transform_t t; + + surface_canvas = (SwCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat); + if (surface_canvas) { + surface = surface_canvas->image; + surface = pixman_image_ref(surface); + } else { + surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE); + } + pixman_transform_init_translate(&t, + pixman_int_to_fixed(-brush->u.pattern.pos.x), + pixman_int_to_fixed(-brush->u.pattern.pos.y)); + pixman_image_set_transform(surface, &t); + pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL); + return surface; + } + case SPICE_BRUSH_TYPE_NONE: + return NULL; + default: + spice_warn_if_reached(); + return NULL; + } + return NULL; +} + +static pixman_image_t *get_image(SpiceCanvas *canvas, int force_opaque) +{ + SwCanvas *sw_canvas = (SwCanvas *)canvas; + pixman_format_code_t format; + + spice_pixman_image_get_format (sw_canvas->image, &format); + if (force_opaque && PIXMAN_FORMAT_A (format) != 0) { + uint32_t *data; + int stride; + int width, height; + + /* Remove alpha bits from format */ + format = (pixman_format_code_t)(((uint32_t)format) & ~(0xf << 12)); + data = pixman_image_get_data (sw_canvas->image); + stride = pixman_image_get_stride (sw_canvas->image); + width = pixman_image_get_width (sw_canvas->image); + height = pixman_image_get_height (sw_canvas->image); + return pixman_image_create_bits (format, width, height, data, stride); + } else { + pixman_image_ref(sw_canvas->image); + } + + return sw_canvas->image; +} + +static void copy_region(SpiceCanvas *spice_canvas, + pixman_region32_t *dest_region, + int dx, int dy) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_box32_t *dest_rects; + int n_rects; + int i, j, end_line; + + dest_rects = pixman_region32_rectangles(dest_region, &n_rects); + + if (dy > 0) { + if (dx >= 0) { + /* south-east: copy x and y in reverse order */ + for (i = n_rects - 1; i >= 0; i--) { + spice_pixman_copy_rect(canvas->image, + dest_rects[i].x1 - dx, dest_rects[i].y1 - dy, + dest_rects[i].x2 - dest_rects[i].x1, + dest_rects[i].y2 - dest_rects[i].y1, + dest_rects[i].x1, dest_rects[i].y1); + } + } else { + /* south-west: Copy y in reverse order, but x in forward order */ + i = n_rects - 1; + + while (i >= 0) { + /* Copy all rects with same y in forward order */ + for (end_line = i - 1; + end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1; + end_line--) { + } + for (j = end_line + 1; j <= i; j++) { + spice_pixman_copy_rect(canvas->image, + dest_rects[j].x1 - dx, dest_rects[j].y1 - dy, + dest_rects[j].x2 - dest_rects[j].x1, + dest_rects[j].y2 - dest_rects[j].y1, + dest_rects[j].x1, dest_rects[j].y1); + } + i = end_line; + } + } + } else { + if (dx > 0) { + /* north-east: copy y in forward order, but x in reverse order */ + i = 0; + + while (i < n_rects) { + /* Copy all rects with same y in reverse order */ + for (end_line = i; + end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1; + end_line++) { + } + for (j = end_line - 1; j >= i; j--) { + spice_pixman_copy_rect(canvas->image, + dest_rects[j].x1 - dx, dest_rects[j].y1 - dy, + dest_rects[j].x2 - dest_rects[j].x1, + dest_rects[j].y2 - dest_rects[j].y1, + dest_rects[j].x1, dest_rects[j].y1); + } + i = end_line; + } + } else { + /* north-west: Copy x and y in forward order */ + for (i = 0; i < n_rects; i++) { + spice_pixman_copy_rect(canvas->image, + dest_rects[i].x1 - dx, dest_rects[i].y1 - dy, + dest_rects[i].x2 - dest_rects[i].x1, + dest_rects[i].y2 - dest_rects[i].y1, + dest_rects[i].x1, dest_rects[i].y1); + } + } + } +} + +static void fill_solid_spans(SpiceCanvas *spice_canvas, + SpicePoint *points, + int *widths, + int n_spans, + uint32_t color) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + int i; + + for (i = 0; i < n_spans; i++) { + spice_pixman_fill_rect(canvas->image, + points[i].x, points[i].y, + widths[i], + 1, + color); + } +} + +static void fill_solid_rects(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + uint32_t color) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + int i; + + for (i = 0; i < n_rects; i++) { + spice_pixman_fill_rect(canvas->image, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + color); + } +} + +static void fill_solid_rects_rop(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + uint32_t color, + SpiceROP rop) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + int i; + + for (i = 0; i < n_rects; i++) { + spice_pixman_fill_rect_rop(canvas->image, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + color, rop); + } +} + +static void __fill_tiled_rects(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + int i; + + for (i = 0; i < n_rects; i++) { + spice_pixman_tile_rect(canvas->image, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + tile, offset_x, offset_y); + } +} + +static void fill_tiled_rects(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y) +{ + __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y); +} + +static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + SpiceCanvas *surface_canvas, + int offset_x, int offset_y) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __fill_tiled_rects(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x, + offset_y); +} + +static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y, + SpiceROP rop) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + int i; + + for (i = 0; i < n_rects; i++) { + spice_pixman_tile_rect_rop(canvas->image, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + tile, offset_x, offset_y, + rop); + } +} +static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + pixman_image_t *tile, + int offset_x, int offset_y, + SpiceROP rop) +{ + __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop); +} + +static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas, + pixman_box32_t *rects, + int n_rects, + SpiceCanvas *surface_canvas, + int offset_x, int offset_y, + SpiceROP rop) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __fill_tiled_rects_rop(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x, + offset_y, rop); +} + +/* Some pixman implementations of OP_OVER on xRGB32 sets + the high bit to 0xff (which is the right value if the + destination was ARGB32, and it should be ignored for + xRGB32. However, this fills our alpha bits with + data that is not wanted or expected by windows, and its + causing us to send rgba images rather than rgb images to + the client. So, we manually clear these bytes. */ +static void clear_dest_alpha(pixman_image_t *dest, + int x, int y, + int width, int height) +{ + uint32_t *data; + int stride; + int w, h; + + w = pixman_image_get_width(dest); + h = pixman_image_get_height(dest); + + if (x + width <= 0 || x >= w || + y + height <= 0 || y >= h || + width == 0 || height == 0) { + return; + } + + if (x < 0) { + width += x; + x = 0; + } + if (x + width > w) { + width = w - x; + } + + if (y < 0) { + height += y; + y = 0; + } + if (y + height > h) { + height = h - y; + } + + stride = pixman_image_get_stride(dest); + data = (uint32_t *) ( + (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x); + + if ((*data & 0xff000000U) == 0xff000000U) { + spice_pixman_fill_rect_rop(dest, + x, y, width, height, + 0x00ffffff, SPICE_ROP_AND); + } +} + +static void __blit_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_box32_t *rects; + int n_rects, i; + + rects = pixman_region32_rectangles(region, &n_rects); + + for (i = 0; i < n_rects; i++) { + int src_x, src_y, dest_x, dest_y, width, height; + + dest_x = rects[i].x1; + dest_y = rects[i].y1; + width = rects[i].x2 - rects[i].x1; + height = rects[i].y2 - rects[i].y1; + + src_x = rects[i].x1 - offset_x; + src_y = rects[i].y1 - offset_y; + + spice_pixman_blit(canvas->image, + src_image, + src_x, src_y, + dest_x, dest_y, + width, height); + } +} + +static void blit_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y) +{ + __blit_image(spice_canvas, region, src_image, offset_x, offset_y); +} + +static void blit_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int offset_x, int offset_y) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __blit_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y); +} + +static void __blit_image_rop(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + SpiceROP rop) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_box32_t *rects; + int n_rects, i; + + rects = pixman_region32_rectangles(region, &n_rects); + + for (i = 0; i < n_rects; i++) { + int src_x, src_y, dest_x, dest_y, width, height; + + dest_x = rects[i].x1; + dest_y = rects[i].y1; + width = rects[i].x2 - rects[i].x1; + height = rects[i].y2 - rects[i].y1; + + src_x = rects[i].x1 - offset_x; + src_y = rects[i].y1 - offset_y; + + spice_pixman_blit_rop(canvas->image, + src_image, + src_x, src_y, + dest_x, dest_y, + width, height, rop); + } +} + +static void blit_image_rop(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + SpiceROP rop) +{ + __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop); +} + +static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int offset_x, int offset_y, + SpiceROP rop) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __blit_image_rop(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, rop); +} + + + +static void __scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_transform_t transform; + pixman_fixed_t fsx, fsy; + + fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; + fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; + + pixman_image_set_clip_region32(canvas->image, region); + + pixman_transform_init_scale(&transform, fsx, fsy); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed (src_x), + pixman_int_to_fixed (src_y)); + + pixman_image_set_transform(src, &transform); + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || + scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); + pixman_image_set_filter(src, + (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? + PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, + NULL, 0); + + pixman_image_composite32(PIXMAN_OP_SRC, + src, NULL, canvas->image, + 0, 0, /* src */ + 0, 0, /* mask */ + dest_x, dest_y, /* dst */ + dest_width, dest_height); + + pixman_transform_init_identity(&transform); + pixman_image_set_transform(src, &transform); + + pixman_image_set_clip_region32(canvas->image, NULL); +} + +static void scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode) +{ + __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y, + dest_width,dest_height,scale_mode); +} + +static void scale_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width, + src_height, dest_x, dest_y, dest_width,dest_height,scale_mode); +} + +static void __scale_image_rop(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, SpiceROP rop) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_transform_t transform; + pixman_image_t *scaled; + pixman_box32_t *rects; + int n_rects, i; + pixman_fixed_t fsx, fsy; + pixman_format_code_t format; + + fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; + fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; + + spice_return_if_fail(spice_pixman_image_get_format(src, &format)); + scaled = pixman_image_create_bits(format, + dest_width, + dest_height, + NULL, 0); + + pixman_region32_translate(region, -dest_x, -dest_y); + pixman_image_set_clip_region32(scaled, region); + + pixman_transform_init_scale(&transform, fsx, fsy); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed (src_x), + pixman_int_to_fixed (src_y)); + + pixman_image_set_transform(src, &transform); + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || + scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); + pixman_image_set_filter(src, + (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? + PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, + NULL, 0); + + pixman_image_composite32(PIXMAN_OP_SRC, + src, NULL, scaled, + 0, 0, /* src */ + 0, 0, /* mask */ + 0, 0, /* dst */ + dest_width, + dest_height); + + pixman_transform_init_identity(&transform); + pixman_image_set_transform(src, &transform); + + /* Translate back */ + pixman_region32_translate(region, dest_x, dest_y); + + rects = pixman_region32_rectangles(region, &n_rects); + + for (i = 0; i < n_rects; i++) { + spice_pixman_blit_rop(canvas->image, + scaled, + rects[i].x1 - dest_x, + rects[i].y1 - dest_y, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + rop); + } + + pixman_image_unref(scaled); +} + +static void scale_image_rop(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, SpiceROP rop) +{ + __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, + dest_y, dest_width, dest_height, scale_mode, rop); +} + +static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, SpiceROP rop) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __scale_image_rop(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width, + src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop); +} + +static pixman_image_t *canvas_get_as_surface(SwCanvas *canvas, + int with_alpha) +{ + pixman_image_t *target; + + if (with_alpha && + canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) { + target = pixman_image_create_bits(PIXMAN_a8r8g8b8, + pixman_image_get_width(canvas->image), + pixman_image_get_height(canvas->image), + pixman_image_get_data(canvas->image), + pixman_image_get_stride(canvas->image)); + } else { + target = pixman_image_ref(canvas->image); + } + + return target; +} + +static void __blend_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int overall_alpha) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_image_t *mask, *dest; + + dest = canvas_get_as_surface(canvas, dest_has_alpha); + + pixman_image_set_clip_region32(dest, region); + + mask = NULL; + if (overall_alpha != 0xff) { + pixman_color_t color = { 0, 0, 0, 0 }; + color.alpha = overall_alpha * 0x101; + mask = pixman_image_create_solid_fill(&color); + } + + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + + pixman_image_composite32(PIXMAN_OP_OVER, + src, mask, dest, + src_x, src_y, /* src */ + 0, 0, /* mask */ + dest_x, dest_y, /* dst */ + width, + height); + + if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB && + !dest_has_alpha) { + clear_dest_alpha(dest, dest_x, dest_y, width, height); + } + + if (mask) { + pixman_image_unref(mask); + } + + pixman_image_set_clip_region32(dest, NULL); + pixman_image_unref(dest); +} + +static void blend_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int overall_alpha) +{ + __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, + dest_x, dest_y, width, height, + overall_alpha); +} + +static void blend_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + SpiceCanvas *surface_canvas, + int src_has_alpha, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int overall_alpha) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + pixman_image_t *src; + + src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha); + __blend_image(spice_canvas, region, dest_has_alpha, + src, src_x, src_y, + dest_x, dest_y, + width, height, overall_alpha); + pixman_image_unref(src); +} + +static void __blend_scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, + int overall_alpha) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_transform_t transform; + pixman_image_t *mask, *dest; + pixman_fixed_t fsx, fsy; + + fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; + fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; + + dest = canvas_get_as_surface(canvas, dest_has_alpha); + + pixman_image_set_clip_region32(dest, region); + + pixman_transform_init_scale(&transform, fsx, fsy); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed (src_x), + pixman_int_to_fixed (src_y)); + + mask = NULL; + if (overall_alpha != 0xff) { + pixman_color_t color = { 0, 0, 0, 0 }; + color.alpha = overall_alpha * 0x101; + mask = pixman_image_create_solid_fill(&color); + } + + pixman_image_set_transform(src, &transform); + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + spice_return_if_fail(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || + scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); + pixman_image_set_filter(src, + (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? + PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, + NULL, 0); + + pixman_image_composite32(PIXMAN_OP_OVER, + src, mask, dest, + 0, 0, /* src */ + 0, 0, /* mask */ + dest_x, dest_y, /* dst */ + dest_width, dest_height); + + if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB && + !dest_has_alpha) { + clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height); + } + + pixman_transform_init_identity(&transform); + pixman_image_set_transform(src, &transform); + + if (mask) { + pixman_image_unref(mask); + } + + pixman_image_set_clip_region32(dest, NULL); + pixman_image_unref(dest); +} + +static void blend_scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, + int overall_alpha) +{ + __blend_scale_image(spice_canvas, region, dest_has_alpha, + src, src_x, src_y, src_width, src_height, + dest_x, dest_y, dest_width, dest_height, + scale_mode, overall_alpha); +} + +static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + int dest_has_alpha, + SpiceCanvas *surface_canvas, + int src_has_alpha, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + int scale_mode, + int overall_alpha) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + pixman_image_t *src; + + src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha); + __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width, + src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, + overall_alpha); + pixman_image_unref(src); +} + +static void __colorkey_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + uint32_t transparent_color) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_box32_t *rects; + int n_rects, i; + + rects = pixman_region32_rectangles(region, &n_rects); + + for (i = 0; i < n_rects; i++) { + int src_x, src_y, dest_x, dest_y, width, height; + + dest_x = rects[i].x1; + dest_y = rects[i].y1; + width = rects[i].x2 - rects[i].x1; + height = rects[i].y2 - rects[i].y1; + + src_x = rects[i].x1 - offset_x; + src_y = rects[i].y1 - offset_y; + + spice_pixman_blit_colorkey(canvas->image, + src_image, + src_x, src_y, + dest_x, dest_y, + width, height, + transparent_color); + } +} + +static void colorkey_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src_image, + int offset_x, int offset_y, + uint32_t transparent_color) +{ + __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color); +} + +static void colorkey_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int offset_x, int offset_y, + uint32_t transparent_color) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __colorkey_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, + transparent_color); +} + +static void __colorkey_scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + uint32_t transparent_color) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_transform_t transform; + pixman_image_t *scaled; + pixman_box32_t *rects; + int n_rects, i; + pixman_fixed_t fsx, fsy; + pixman_format_code_t format; + + fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; + fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; + + spice_return_if_fail(spice_pixman_image_get_format(src, &format)); + scaled = pixman_image_create_bits(format, + dest_width, + dest_height, + NULL, 0); + + pixman_region32_translate(region, -dest_x, -dest_y); + pixman_image_set_clip_region32(scaled, region); + + pixman_transform_init_scale(&transform, fsx, fsy); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed (src_x), + pixman_int_to_fixed (src_y)); + + pixman_image_set_transform(src, &transform); + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + pixman_image_set_filter(src, + PIXMAN_FILTER_NEAREST, + NULL, 0); + + pixman_image_composite32(PIXMAN_OP_SRC, + src, NULL, scaled, + 0, 0, /* src */ + 0, 0, /* mask */ + 0, 0, /* dst */ + dest_width, + dest_height); + + pixman_transform_init_identity(&transform); + pixman_image_set_transform(src, &transform); + + /* Translate back */ + pixman_region32_translate(region, dest_x, dest_y); + + rects = pixman_region32_rectangles(region, &n_rects); + + for (i = 0; i < n_rects; i++) { + spice_pixman_blit_colorkey(canvas->image, + scaled, + rects[i].x1 - dest_x, + rects[i].y1 - dest_y, + rects[i].x1, rects[i].y1, + rects[i].x2 - rects[i].x1, + rects[i].y2 - rects[i].y1, + transparent_color); + } + + pixman_image_unref(scaled); +} + +static void colorkey_scale_image(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + pixman_image_t *src, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + uint32_t transparent_color) +{ + __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, + dest_y, dest_width, dest_height, transparent_color); +} + +static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas, + pixman_region32_t *region, + SpiceCanvas *surface_canvas, + int src_x, int src_y, + int src_width, int src_height, + int dest_x, int dest_y, + int dest_width, int dest_height, + uint32_t transparent_color) +{ + SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; + __colorkey_scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, + src_width, src_height, dest_x, dest_y, dest_width, dest_height, + transparent_color); +} + +static void canvas_put_image(SpiceCanvas *spice_canvas, +#ifdef WIN32 + HDC dc, +#endif + const SpiceRect *dest, const uint8_t *src_data, + uint32_t src_width, uint32_t src_height, int src_stride, + const QRegion *clip) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_image_t *src; + uint32_t dest_width; + uint32_t dest_height; + double sx, sy; + pixman_transform_t transform; + + src = pixman_image_create_bits(PIXMAN_x8r8g8b8, + src_width, + src_height, + (uint32_t*)src_data, + src_stride); + + + if (clip) { + pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip); + } + + dest_width = dest->right - dest->left; + dest_height = dest->bottom - dest->top; + + if (dest_width != src_width || dest_height != src_height) { + sx = (double)(src_width) / (dest_width); + sy = (double)(src_height) / (dest_height); + + pixman_transform_init_scale(&transform, + pixman_double_to_fixed(sx), + pixman_double_to_fixed(sy)); + pixman_image_set_transform(src, &transform); + pixman_image_set_filter(src, + PIXMAN_FILTER_NEAREST, + NULL, 0); + } + + pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); + + pixman_image_composite32(PIXMAN_OP_SRC, + src, NULL, canvas->image, + 0, 0, /* src */ + 0, 0, /* mask */ + dest->left, dest->top, /* dst */ + dest_width, dest_height); + + + if (clip) { + pixman_image_set_clip_region32(canvas->image, NULL); + } + pixman_image_unref(src); +} + + +static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, + SpiceClip *clip, SpiceText *text) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_region32_t dest_region; + pixman_image_t *str_mask, *brush; + SpiceString *str; + SpicePoint pos = { 0, 0 }; + int depth; + + pixman_region32_init_rect(&dest_region, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); + + canvas_clip_pixman(&canvas->base, &dest_region, clip); + + if (!pixman_region32_not_empty(&dest_region)) { + touch_brush(&canvas->base, &text->fore_brush); + touch_brush(&canvas->base, &text->back_brush); + pixman_region32_fini(&dest_region); + return; + } + + if (!rect_is_empty(&text->back_area)) { + pixman_region32_t back_region; + + /* Nothing else makes sense for text and we should deprecate it + * and actually it means OVER really */ + spice_return_if_fail(text->fore_mode == SPICE_ROPD_OP_PUT); + + pixman_region32_init_rect(&back_region, + text->back_area.left, + text->back_area.top, + text->back_area.right - text->back_area.left, + text->back_area.bottom - text->back_area.top); + + pixman_region32_intersect(&back_region, &back_region, &dest_region); + + if (pixman_region32_not_empty(&back_region)) { + draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY); + } + + pixman_region32_fini(&back_region); + } + str = (SpiceString *)SPICE_GET_ADDRESS(text->str); + + if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) { + depth = 1; + } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) { + depth = 4; + } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) { + spice_warning("untested path A8 glyphs"); + depth = 8; + } else { + spice_warning("unsupported path vector glyphs"); + pixman_region32_fini (&dest_region); + return; + } + + brush = canvas_get_pixman_brush(canvas, &text->fore_brush); + + str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos); + if (brush) { + pixman_image_set_clip_region32(canvas->image, &dest_region); + + pixman_image_composite32(PIXMAN_OP_OVER, + brush, + str_mask, + canvas->image, + 0, 0, + 0, 0, + pos.x, pos.y, + pixman_image_get_width(str_mask), + pixman_image_get_height(str_mask)); + if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) { + clear_dest_alpha(canvas->image, pos.x, pos.y, + pixman_image_get_width(str_mask), + pixman_image_get_height(str_mask)); + } + pixman_image_unref(brush); + + pixman_image_set_clip_region32(canvas->image, NULL); + } + pixman_image_unref(str_mask); + pixman_region32_fini(&dest_region); +} + +static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest, + int dest_stride, const SpiceRect *area) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + pixman_image_t* surface; + uint8_t *src; + int src_stride; + uint8_t *dest_end; + int bpp; + + spice_return_if_fail(canvas && area); + + surface = canvas->image; + + bpp = spice_pixman_image_get_bpp(surface) / 8; + + src_stride = pixman_image_get_stride(surface); + src = (uint8_t *)pixman_image_get_data(surface) + + area->top * src_stride + area->left * bpp; + dest_end = dest + (area->bottom - area->top) * dest_stride; + for (; dest != dest_end; dest += dest_stride, src += src_stride) { + memcpy(dest, src, (area->right - area->left) * bpp); + } +} + +static void canvas_clear(SpiceCanvas *spice_canvas) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + spice_pixman_fill_rect(canvas->image, + 0, 0, + pixman_image_get_width(canvas->image), + pixman_image_get_height(canvas->image), + 0); +} + +static void canvas_destroy(SpiceCanvas *spice_canvas) +{ + SwCanvas *canvas = (SwCanvas *)spice_canvas; + if (!canvas) { + return; + } + pixman_image_unref(canvas->image); + canvas_base_destroy(&canvas->base); + free(canvas->private_data); + free(canvas); +} + +static SpiceCanvasOps sw_canvas_ops; + +static SpiceCanvas *canvas_create_common(pixman_image_t *image, + uint32_t format + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ) +{ + SwCanvas *canvas; + + spice_pixman_image_set_format(image, + spice_surface_format_to_pixman (format)); + + canvas = spice_new0(SwCanvas, 1); + canvas_base_init(&canvas->base, &sw_canvas_ops, + pixman_image_get_width (image), + pixman_image_get_height (image), + format + , bits_cache +#ifdef SW_CANVAS_CACHE + , palette_cache +#endif + , surfaces + , glz_decoder + , jpeg_decoder + , zlib_decoder + ); + canvas->private_data = NULL; + canvas->private_data_size = 0; + + canvas->image = image; + + return (SpiceCanvas *)canvas; +} + +SpiceCanvas *canvas_create(int width, int height, uint32_t format + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ) +{ + pixman_image_t *image; + + image = pixman_image_create_bits(spice_surface_format_to_pixman (format), + width, height, NULL, 0); + + return canvas_create_common(image, format + , bits_cache +#ifdef SW_CANVAS_CACHE + , palette_cache +#endif + , surfaces + , glz_decoder + , jpeg_decoder + , zlib_decoder + ); +} + +SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, + uint8_t *data, int stride + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ) +{ + pixman_image_t *image; + + image = pixman_image_create_bits(spice_surface_format_to_pixman (format), + width, height, (uint32_t *)data, stride); + + return canvas_create_common(image, format + , bits_cache +#ifdef SW_CANVAS_CACHE + , palette_cache +#endif + , surfaces + , glz_decoder + , jpeg_decoder + , zlib_decoder + ); +} + +SPICE_CONSTRUCTOR_FUNC(sw_canvas_global_init) //unsafe global function +{ + canvas_base_init_ops(&sw_canvas_ops); + sw_canvas_ops.draw_text = canvas_draw_text; + sw_canvas_ops.put_image = canvas_put_image; + sw_canvas_ops.clear = canvas_clear; + sw_canvas_ops.read_bits = canvas_read_bits; + sw_canvas_ops.destroy = canvas_destroy; + + sw_canvas_ops.fill_solid_spans = fill_solid_spans; + sw_canvas_ops.fill_solid_rects = fill_solid_rects; + sw_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop; + sw_canvas_ops.fill_tiled_rects = fill_tiled_rects; + sw_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface; + sw_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop; + sw_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface; + sw_canvas_ops.blit_image = blit_image; + sw_canvas_ops.blit_image_from_surface = blit_image_from_surface; + sw_canvas_ops.blit_image_rop = blit_image_rop; + sw_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface; + sw_canvas_ops.scale_image = scale_image; + sw_canvas_ops.scale_image_from_surface = scale_image_from_surface; + sw_canvas_ops.scale_image_rop = scale_image_rop; + sw_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface; + sw_canvas_ops.blend_image = blend_image; + sw_canvas_ops.blend_image_from_surface = blend_image_from_surface; + sw_canvas_ops.blend_scale_image = blend_scale_image; + sw_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface; + sw_canvas_ops.colorkey_image = colorkey_image; + sw_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface; + sw_canvas_ops.colorkey_scale_image = colorkey_scale_image; + sw_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface; + sw_canvas_ops.copy_region = copy_region; + sw_canvas_ops.get_image = get_image; +} diff --git a/spice-common/common/sw_canvas.h b/spice-common/common/sw_canvas.h new file mode 100644 index 0000000..8039142 --- /dev/null +++ b/spice-common/common/sw_canvas.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _H__CANVAS +#define _H__CANVAS + +#include +#include + +#include "draw.h" +#include "pixman_utils.h" +#include "canvas_base.h" +#include "region.h" + +SPICE_BEGIN_DECLS + +SpiceCanvas *canvas_create(int width, int height, uint32_t format + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ); + +SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, int stride + , SpiceImageCache *bits_cache +#ifdef SW_CANVAS_CACHE + , SpicePaletteCache *palette_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder + , SpiceJpegDecoder *jpeg_decoder + , SpiceZlibDecoder *zlib_decoder + ); + + +static inline SPICE_GNUC_DEPRECATED void sw_canvas_init(void) {} + +SPICE_END_DECLS + +#endif diff --git a/spice-common/common/verify.h b/spice-common/common/verify.h new file mode 100644 index 0000000..8445e3d --- /dev/null +++ b/spice-common/common/verify.h @@ -0,0 +1,245 @@ +/* Compile-time assert-like macros. + + Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_VERIFY_H +# define _GL_VERIFY_H + + +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. + This is supported by GCC 4.6.0 and later, in C mode, and its use + here generates easier-to-read diagnostics when verify (R) fails. + + Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. + This will likely be supported by future GCC versions, in C++ mode. + + Use this only with GCC. If we were willing to slow 'configure' + down we could also use it with other compilers, but since this + affects only the quality of diagnostics, why bother? */ +# if (4 < __GNUC__ || (__GNUC__ == 4 && 6 <= __GNUC_MINOR__)) && !defined __cplusplus +# define _GL_HAVE__STATIC_ASSERT 1 +# endif +/* The condition (99 < __GNUC__) is temporary, until we know about the + first G++ release that supports static_assert. */ +# if (99 < __GNUC__) && defined __cplusplus +# define _GL_HAVE_STATIC_ASSERT 1 +# endif + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + If _Static_assert works, verify (R) uses it directly. Similarly, + _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct + that is an operand of sizeof. + + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: + + * The first step is ((R) ? 1 : -1). Given an expression R, of + integral or boolean or floating-point type, this yields an + expression of integral type, whose value is later verified to be + constant and nonnegative. + + * Next this expression W is wrapped in a type + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: W; + }. + If W is negative, this yields a compile-time error. No compiler can + deal with a bit-field of negative size. + + One might think that an array size check would have the same + effect, that is, that the type struct { unsigned int dummy[W]; } + would work as well. However, inside a function, some compilers + (such as C++ compilers and GNU C) allow local parameters and + variables inside array size expressions. With these compilers, + an array size check would not properly diagnose this misuse of + the verify macro: + + void function (int n) { verify (n < 0); } + + * For the verify macro, the struct _gl_verify_type will need to + somehow be embedded into a declaration. To be portable, this + declaration must declare an object, a constant, a function, or a + typedef name. If the declared entity uses the type directly, + such as in + + struct dummy {...}; + typedef struct {...} dummy; + extern struct {...} *dummy; + extern void dummy (struct {...} *); + extern struct {...} *dummy (void); + + two uses of the verify macro would yield colliding declarations + if the entity names are not disambiguated. A workaround is to + attach the current line number to the entity name: + + #define _GL_CONCAT0(x, y) x##y + #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) + extern struct {...} * _GL_CONCAT (dummy, __LINE__); + + But this has the problem that two invocations of verify from + within the same macro would collide, since the __LINE__ value + would be the same for both invocations. (The GCC __COUNTER__ + macro solves this problem, but is not portable.) + + A solution is to use the sizeof operator. It yields a number, + getting rid of the identity of the type. Declarations like + + extern int dummy [sizeof (struct {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + + can be repeated. + + * Should the implementation use a named struct or an unnamed struct? + Which of the following alternatives can be used? + + extern int dummy [sizeof (struct {...})]; + extern int dummy [sizeof (struct _gl_verify_type {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern void dummy (int [sizeof (struct _gl_verify_type {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; + + In the second and sixth case, the struct type is exported to the + outer scope; two such declarations therefore collide. GCC warns + about the first, third, and fourth cases. So the only remaining + possibility is the fifth case: + + extern int (*dummy (void)) [sizeof (struct {...})]; + + * GCC warns about duplicate declarations of the dummy function if + -Wredundant-decls is used. GCC 4.3 and later have a builtin + __COUNTER__ macro that can let us generate unique identifiers for + each dummy function, to suppress this warning. + + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. + + * GCC warns if -Wnested-externs is enabled and verify() is used + within a function body; but inside a function, you can always + arrange to use verify_expr() instead. + + * In C++, any struct definition inside sizeof is invalid. + Use a template type to work around the problem. */ + +/* Concatenate two preprocessor tokens. */ +# define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) +# define _GL_CONCAT0(x, y) x##y + +/* _GL_COUNTER is an integer, preferably one that changes each time we + use it. Use __COUNTER__ if it works, falling back on __LINE__ + otherwise. __LINE__ isn't perfect, but it's better than a + constant. */ +# if defined __COUNTER__ && __COUNTER__ != __COUNTER__ +# define _GL_COUNTER __COUNTER__ +# else +# define _GL_COUNTER __LINE__ +# endif + +/* Generate a symbol with the given prefix, making it unique if + possible. */ +# define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) + +/* Verify requirement R at compile-time, as an integer constant expression + that returns 1. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. */ + +# define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ + (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) + +# ifdef __cplusplus +# if !GNULIB_defined_struct__gl_verify_type +template + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + _gl_verify_type<(R) ? 1 : -1> +# elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { \ + _Static_assert (R, DIAGNOSTIC); \ + int _gl_dummy; \ + } +# else +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } +# endif + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. + + Unfortunately, unlike C11, this implementation must appear as an + ordinary declaration, and cannot appear inside struct { ... }. */ + +# ifdef _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY _Static_assert +# else +# define _GL_VERIFY(R, DIAGNOSTIC) \ + extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ + [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +# endif + +/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ +# ifdef _GL_STATIC_ASSERT_H +# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert +# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) +# endif +# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert +# define static_assert _Static_assert /* C11 requires this #define. */ +# endif +# endif + +/* @assert.h omit start@ */ + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + There are two macros, since no single macro can be used in all + contexts in C. verify_true (R) is for scalar contexts, including + integer constant expression contexts. verify (R) is for declaration + contexts, e.g., the top level. */ + +/* Verify requirement R at compile-time, as an integer constant expression. + Return 1. This is equivalent to verify_expr (R, 1). + + verify_true is obsolescent; please use verify_expr instead. */ + +# define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")") + +/* Verify requirement R at compile-time. Return the value of the + expression E. */ + +# define verify_expr(R, E) \ + (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. */ + +# define verify(R) _GL_VERIFY (R, "verify (" #R ")") + +/* @assert.h omit end@ */ + +#endif diff --git a/spice-common/config.h.in b/spice-common/config.h.in new file mode 100644 index 0000000..5aa3d6d --- /dev/null +++ b/spice-common/config.h.in @@ -0,0 +1,231 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define if we have celt051 codec */ +#undef HAVE_CELT051 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `dup2' function. */ +#undef HAVE_DUP2 + +/* Define to 1 if you have the `floor' function. */ +#undef HAVE_FLOOR + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `inet_ntoa' function. */ +#undef HAVE_INET_NTOA + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* 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 `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define if we have OPUS */ +#undef HAVE_OPUS + +/* Define to 1 if you have the `pow' function. */ +#undef HAVE_POW + +/* Define to 1 if you have the `sqrt' function. */ +#undef HAVE_SQRT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* 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 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_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if supporting smartcard proxying */ +#undef USE_SMARTCARD + +/* Define if supporting smartcard proxying without libcacard.h */ +#undef USE_SMARTCARD_012 + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef int16_t + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to the type of a signed integer type of width exactly 8 bits if such + a type exists and the standard includes do not define it. */ +#undef int8_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork + + +/* argh.. this is evil */ +#if defined(FIXME_SERVER_SMARTCARD) && defined(USE_SMARTCARD) +%:undef USE_SMARTCARD +#endif + diff --git a/spice-common/configure b/spice-common/configure new file mode 100755 index 0000000..5453864 --- /dev/null +++ b/spice-common/configure @@ -0,0 +1,17656 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for spice-common noversion. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: spice-devel@lists.freedesktop.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='spice-common' +PACKAGE_TARNAME='spice-common' +PACKAGE_VERSION='noversion' +PACKAGE_STRING='spice-common noversion' +PACKAGE_BUGREPORT='spice-devel@lists.freedesktop.org' +PACKAGE_URL='' + +ac_unique_file="common/bitops.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='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +SPICE_COMMON_LIBS +SPICE_COMMON_CFLAGS +OPENSSL_LIBS +OPENSSL_CFLAGS +HAVE_OPUS_FALSE +HAVE_OPUS_TRUE +OPUS_LIBS +OPUS_CFLAGS +GLIB2_LIBS +GLIB2_CFLAGS +HAVE_CELT051_FALSE +HAVE_CELT051_TRUE +CELT051_LIBS +CELT051_CFLAGS +HAVE_SMARTCARD_FALSE +HAVE_SMARTCARD_TRUE +SMARTCARD_LIBS +SMARTCARD_CFLAGS +PIXMAN_LIBS +PIXMAN_CFLAGS +pkgpyexecdir +pyexecdir +pkgpythondir +pythondir +PYTHON_PLATFORM +PYTHON_EXEC_PREFIX +PYTHON_PREFIX +PYTHON_VERSION +PYTHON +PROTOCOL_LIBS +PROTOCOL_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +LIBOBJS +ALLOCA +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +ac_ct_AR +AR +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +enable_silent_rules +enable_maintainer_mode +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_python_checks +enable_smartcard +enable_celt051 +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +PROTOCOL_CFLAGS +PROTOCOL_LIBS +PYTHON +PIXMAN_CFLAGS +PIXMAN_LIBS +SMARTCARD_CFLAGS +SMARTCARD_LIBS +CELT051_CFLAGS +CELT051_LIBS +GLIB2_CFLAGS +GLIB2_LIBS +OPUS_CFLAGS +OPUS_LIBS +OPENSSL_CFLAGS +OPENSSL_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures spice-common noversion 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/spice-common] + --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 + case $ac_init_help in + short | recursive ) echo "Configuration of spice-common noversion:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-python-checks=[yes/no] + Enable checks for Python modules needed to build + from git [default=no] + --enable-smartcard=[yes/no/auto] + Enable smartcard support [default=auto] + --disable-celt051 Disable celt051 audio codec (enabled by default) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + PROTOCOL_CFLAGS + C compiler flags for PROTOCOL, overriding pkg-config + PROTOCOL_LIBS + linker flags for PROTOCOL, overriding pkg-config + PYTHON the Python interpreter + PIXMAN_CFLAGS + C compiler flags for PIXMAN, overriding pkg-config + PIXMAN_LIBS linker flags for PIXMAN, overriding pkg-config + SMARTCARD_CFLAGS + C compiler flags for SMARTCARD, overriding pkg-config + SMARTCARD_LIBS + linker flags for SMARTCARD, overriding pkg-config + CELT051_CFLAGS + C compiler flags for CELT051, overriding pkg-config + CELT051_LIBS + linker flags for CELT051, overriding pkg-config + GLIB2_CFLAGS + C compiler flags for GLIB2, overriding pkg-config + GLIB2_LIBS linker flags for GLIB2, overriding pkg-config + OPUS_CFLAGS C compiler flags for OPUS, overriding pkg-config + OPUS_LIBS linker flags for OPUS, overriding pkg-config + OPENSSL_CFLAGS + C compiler flags for OPENSSL, overriding pkg-config + OPENSSL_LIBS + linker flags for OPENSSL, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +spice-common configure noversion +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------ ## +## Report this to spice-devel@lists.freedesktop.org ## +## ------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_find_intX_t LINENO BITS VAR +# ----------------------------------- +# Finds a signed integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_intX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 +$as_echo_n "checking for int$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) + < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_intX_t + +# ac_fn_c_find_uintX_t LINENO BITS VAR +# ------------------------------------ +# Finds an unsigned integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_uintX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 +$as_echo_n "checking for uint$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_uintX_t +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 spice-common $as_me noversion, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) 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 +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args=$ac_configure_args" '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +ac_config_headers="$ac_config_headers config.h" + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +# For automake >= 1.12 +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar lib "link -lib" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar lib "link -lib" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 +$as_echo_n "checking the archiver ($AR) interface... " >&6; } +if ${am_cv_ar_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + am_cv_ar_interface=ar + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int some_variable = 0; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 + (eval $am_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 +$as_echo "$am_cv_ar_interface" >&6; } + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + as_fn_error $? "could not determine $AR interface" "$LINENO" 5 + ;; +esac + + +# Checks for programs +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='spice-common' + VERSION='noversion' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -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 ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -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_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + +fi + + +if test "x$ac_cv_prog_cc_c99" = xno; then + as_fn_error $? "C99 compiler is required." "$LINENO" 5 +fi + + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if ${ac_cv_working_alloca_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_alloca_h=yes +else + ac_cv_working_alloca_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if ${ac_cv_func_alloca_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +void *alloca (size_t); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_alloca_works=yes +else + ac_cv_func_alloca_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +$as_echo "#define C_ALLOCA 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if ${ac_cv_os_cray+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then : + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if ${ac_cv_c_stack_direction+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_c_stack_direction=0 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +int +main (int argc, char **argv) +{ + return find_stack_direction (0, argc + !argv + 20) < 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + for ac_header in arpa/inet.h malloc.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/socket.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + # Checks for typedefs, structures, and compiler characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" +case $ac_cv_c_int16_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int16_t $ac_cv_c_int16_t +_ACEOF +;; +esac + + ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" +case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; +esac + + ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" +case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; +esac + + ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" +case $ac_cv_c_int8_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int8_t $ac_cv_c_int8_t +_ACEOF +;; +esac + + ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + + ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" +case $ac_cv_c_uint16_t in #( + no|yes) ;; #( + *) + + +cat >>confdefs.h <<_ACEOF +#define uint16_t $ac_cv_c_uint16_t +_ACEOF +;; + esac + + ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT32_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + + ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT64_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + + ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" +case $ac_cv_c_uint8_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT8_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint8_t $ac_cv_c_uint8_t +_ACEOF +;; + esac + + + # Checks for library functions + # do not check malloc or realloc, since that cannot be cross-compiled checked + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for error_at_line" >&5 +$as_echo_n "checking for error_at_line... " >&6; } +if ${ac_cv_lib_error_at_line+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +error_at_line (0, 0, "", 0, "an error occurred"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_error_at_line=yes +else + ac_cv_lib_error_at_line=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_error_at_line" >&5 +$as_echo "$ac_cv_lib_error_at_line" >&6; } +if test $ac_cv_lib_error_at_line = no; then + case " $LIBOBJS " in + *" error.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS error.$ac_objext" + ;; +esac + +fi + + for ac_header in vfork.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" +if test "x$ac_cv_header_vfork_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VFORK_H 1 +_ACEOF + +fi + +done + +for ac_func in fork vfork +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test "x$ac_cv_func_fork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 +$as_echo_n "checking for working fork... " >&6; } +if ${ac_cv_func_fork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_fork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + return fork () < 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_fork_works=yes +else + ac_cv_func_fork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 +$as_echo "$ac_cv_func_fork_works" >&6; } + +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp*) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 +$as_echo_n "checking for working vfork... " >&6; } +if ${ac_cv_func_vfork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_vfork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Paul Eggert for this test. */ +$ac_includes_default +#include +#ifdef HAVE_VFORK_H +# include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. The compiler + is told about this with #include , but some compilers + (e.g. gcc -O) don't grok . Test for this by using a + static variable whose address is put into a register that is + clobbered by the vfork. */ +static void +#ifdef __cplusplus +sparc_address_test (int arg) +# else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} + +int +main () +{ + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (0); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. This + test uses lots of local variables, at least as many local + variables as main has allocated so far including compiler + temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris + 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should + reuse the register of parent for one of the local variables, + since it will think that parent can't possibly be used any more + in this routine. Assigning to the local variable will thus + munge parent in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent + from child file descriptors. If the child closes a descriptor + before it execs or exits, this munges the parent's descriptor + as well. Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + return ( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_vfork_works=yes +else + ac_cv_func_vfork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 +$as_echo "$ac_cv_func_vfork_works" >&6; } + +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h + +else + +$as_echo "#define vfork fork" >>confdefs.h + +fi +if test "x$ac_cv_func_fork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h + +fi + + for ac_func in dup2 floor inet_ntoa memmove memset pow sqrt +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +# Checks for libraries + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTOCOL" >&5 +$as_echo_n "checking for PROTOCOL... " >&6; } + +if test -n "$PROTOCOL_CFLAGS"; then + pkg_cv_PROTOCOL_CFLAGS="$PROTOCOL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"spice-protocol >= 0.12.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "spice-protocol >= 0.12.10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PROTOCOL_CFLAGS=`$PKG_CONFIG --cflags "spice-protocol >= 0.12.10" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PROTOCOL_LIBS"; then + pkg_cv_PROTOCOL_LIBS="$PROTOCOL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"spice-protocol >= 0.12.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "spice-protocol >= 0.12.10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PROTOCOL_LIBS=`$PKG_CONFIG --libs "spice-protocol >= 0.12.10" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PROTOCOL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "spice-protocol >= 0.12.10" 2>&1` + else + PROTOCOL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "spice-protocol >= 0.12.10" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PROTOCOL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (spice-protocol >= 0.12.10) were not met: + +$PROTOCOL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables PROTOCOL_CFLAGS +and PROTOCOL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables PROTOCOL_CFLAGS +and PROTOCOL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + PROTOCOL_CFLAGS=$pkg_cv_PROTOCOL_CFLAGS + PROTOCOL_LIBS=$pkg_cv_PROTOCOL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + + + + + + # Find any Python interpreter. + if test -z "$PYTHON"; then + for ac_prog in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PYTHON" && break +done +test -n "$PYTHON" || PYTHON=":" + + fi + am_display_PYTHON=python + + + if test "$PYTHON" = :; then + as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 + else + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 +$as_echo_n "checking for $am_display_PYTHON version... " >&6; } +if ${am_cv_python_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 +$as_echo "$am_cv_python_version" >&6; } + PYTHON_VERSION=$am_cv_python_version + + + + PYTHON_PREFIX='${prefix}' + + PYTHON_EXEC_PREFIX='${exec_prefix}' + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 +$as_echo_n "checking for $am_display_PYTHON platform... " >&6; } +if ${am_cv_python_platform+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 +$as_echo "$am_cv_python_platform" >&6; } + PYTHON_PLATFORM=$am_cv_python_platform + + + # Just factor out some code duplication. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[:3] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 +$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } +if ${am_cv_python_pythondir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$prefix" = xNONE + then + am_py_prefix=$ac_default_prefix + else + am_py_prefix=$prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) + am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 +$as_echo "$am_cv_python_pythondir" >&6; } + pythondir=$am_cv_python_pythondir + + + + pkgpythondir=\${pythondir}/$PACKAGE + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 +$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } +if ${am_cv_python_pyexecdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$exec_prefix" = xNONE + then + am_py_exec_prefix=$am_py_prefix + else + am_py_exec_prefix=$exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) + am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 +$as_echo "$am_cv_python_pyexecdir" >&6; } + pyexecdir=$am_cv_python_pyexecdir + + + + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + + + fi + + + # Check whether --enable-python-checks was given. +if test "${enable_python_checks+set}" = set; then : + enableval=$enable_python_checks; +else + enable_python_checks="no" +fi + + if test "x$enable_python_checks" != "xno"; then + + if test -z $PYTHON; + then + PYTHON="python" + fi + PYTHON_NAME=`basename $PYTHON` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking $PYTHON_NAME module: six" >&5 +$as_echo_n "checking $PYTHON_NAME module: six... " >&6; } + $PYTHON -c "import six" 2>/dev/null + if test $? -eq 0; + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + eval HAVE_PYMOD_SIX=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + eval HAVE_PYMOD_SIX=no + # + if test -n "1" + then + as_fn_error $? "failed to find required module six" "$LINENO" 5 + exit 1 + fi + fi + + + if test -z $PYTHON; + then + PYTHON="python" + fi + PYTHON_NAME=`basename $PYTHON` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking $PYTHON_NAME module: pyparsing" >&5 +$as_echo_n "checking $PYTHON_NAME module: pyparsing... " >&6; } + $PYTHON -c "import pyparsing" 2>/dev/null + if test $? -eq 0; + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + eval HAVE_PYMOD_PYPARSING=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + eval HAVE_PYMOD_PYPARSING=no + # + if test -n "1" + then + as_fn_error $? "failed to find required module pyparsing" "$LINENO" 5 + exit 1 + fi + fi + + fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PIXMAN" >&5 +$as_echo_n "checking for PIXMAN... " >&6; } + +if test -n "$PIXMAN_CFLAGS"; then + pkg_cv_PIXMAN_CFLAGS="$PIXMAN_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pixman-1 >= 0.17.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pixman-1 >= 0.17.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PIXMAN_CFLAGS=`$PKG_CONFIG --cflags "pixman-1 >= 0.17.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PIXMAN_LIBS"; then + pkg_cv_PIXMAN_LIBS="$PIXMAN_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pixman-1 >= 0.17.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pixman-1 >= 0.17.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PIXMAN_LIBS=`$PKG_CONFIG --libs "pixman-1 >= 0.17.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PIXMAN_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pixman-1 >= 0.17.7" 2>&1` + else + PIXMAN_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pixman-1 >= 0.17.7" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PIXMAN_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (pixman-1 >= 0.17.7) were not met: + +$PIXMAN_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables PIXMAN_CFLAGS +and PIXMAN_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables PIXMAN_CFLAGS +and PIXMAN_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + PIXMAN_CFLAGS=$pkg_cv_PIXMAN_CFLAGS + PIXMAN_LIBS=$pkg_cv_PIXMAN_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + # Check whether --enable-smartcard was given. +if test "${enable_smartcard+set}" = set; then : + enableval=$enable_smartcard; +else + enable_smartcard="auto" +fi + + + have_smartcard=no + if test "x$enable_smartcard" != "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMARTCARD" >&5 +$as_echo_n "checking for SMARTCARD... " >&6; } + +if test -n "$SMARTCARD_CFLAGS"; then + pkg_cv_SMARTCARD_CFLAGS="$SMARTCARD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 2.5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 2.5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_CFLAGS=`$PKG_CONFIG --cflags "libcacard >= 2.5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SMARTCARD_LIBS"; then + pkg_cv_SMARTCARD_LIBS="$SMARTCARD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 2.5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 2.5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_LIBS=`$PKG_CONFIG --libs "libcacard >= 2.5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcacard >= 2.5.1" 2>&1` + else + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcacard >= 2.5.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SMARTCARD_PKG_ERRORS" >&5 + + have_smartcard=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_smartcard=no +else + SMARTCARD_CFLAGS=$pkg_cv_SMARTCARD_CFLAGS + SMARTCARD_LIBS=$pkg_cv_SMARTCARD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_smartcard=yes +fi + if test "x$have_smartcard" = "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMARTCARD" >&5 +$as_echo_n "checking for SMARTCARD... " >&6; } + +if test -n "$SMARTCARD_CFLAGS"; then + pkg_cv_SMARTCARD_CFLAGS="$SMARTCARD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 0.1.2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 0.1.2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_CFLAGS=`$PKG_CONFIG --cflags "libcacard >= 0.1.2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SMARTCARD_LIBS"; then + pkg_cv_SMARTCARD_LIBS="$SMARTCARD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcacard >= 0.1.2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcacard >= 0.1.2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SMARTCARD_LIBS=`$PKG_CONFIG --libs "libcacard >= 0.1.2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcacard >= 0.1.2" 2>&1` + else + SMARTCARD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcacard >= 0.1.2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SMARTCARD_PKG_ERRORS" >&5 + + have_smartcard=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_smartcard=no +else + SMARTCARD_CFLAGS=$pkg_cv_SMARTCARD_CFLAGS + SMARTCARD_LIBS=$pkg_cv_SMARTCARD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_smartcard=yes have_smartcard_012=yes +fi + fi + if test "x$enable_smartcard" != "xauto" && test "x$have_smartcard" = "xno"; then + as_fn_error $? "\"Smartcard support requested but libcacard could not be found\"" "$LINENO" 5 + fi + if test "x$have_smartcard_012" = "xyes"; then + +$as_echo "#define USE_SMARTCARD_012 1" >>confdefs.h + + fi + if test "x$have_smartcard" = "xyes"; then + +$as_echo "#define USE_SMARTCARD 1" >>confdefs.h + + fi + fi + if test "x$have_smartcard" = "xyes"; then + HAVE_SMARTCARD_TRUE= + HAVE_SMARTCARD_FALSE='#' +else + HAVE_SMARTCARD_TRUE='#' + HAVE_SMARTCARD_FALSE= +fi + + + + # Check whether --enable-celt051 was given. +if test "${enable_celt051+set}" = set; then : + enableval=$enable_celt051; +else + enable_celt051="yes" +fi + + + if test "x$enable_celt051" = "xyes"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CELT051" >&5 +$as_echo_n "checking for CELT051... " >&6; } + +if test -n "$CELT051_CFLAGS"; then + pkg_cv_CELT051_CFLAGS="$CELT051_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"celt051 >= 0.5.1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "celt051 >= 0.5.1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CELT051_CFLAGS=`$PKG_CONFIG --cflags "celt051 >= 0.5.1.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CELT051_LIBS"; then + pkg_cv_CELT051_LIBS="$CELT051_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"celt051 >= 0.5.1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "celt051 >= 0.5.1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CELT051_LIBS=`$PKG_CONFIG --libs "celt051 >= 0.5.1.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CELT051_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "celt051 >= 0.5.1.1" 2>&1` + else + CELT051_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "celt051 >= 0.5.1.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CELT051_PKG_ERRORS" >&5 + + have_celt051=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_celt051=no +else + CELT051_CFLAGS=$pkg_cv_CELT051_CFLAGS + CELT051_LIBS=$pkg_cv_CELT051_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_celt051=yes +fi + else + have_celt051=no + fi + + if test "x$have_celt051" = "xyes"; then + HAVE_CELT051_TRUE= + HAVE_CELT051_FALSE='#' +else + HAVE_CELT051_TRUE='#' + HAVE_CELT051_FALSE= +fi + + if test -z "$HAVE_CELT051_TRUE"; then : + +$as_echo "#define HAVE_CELT051 1" >>confdefs.h + +fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB2" >&5 +$as_echo_n "checking for GLIB2... " >&6; } + +if test -n "$GLIB2_CFLAGS"; then + pkg_cv_GLIB2_CFLAGS="$GLIB2_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB2_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB2_LIBS"; then + pkg_cv_GLIB2_LIBS="$GLIB2_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB2_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22" 2>&1` + else + GLIB2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB2_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22) were not met: + +$GLIB2_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GLIB2_CFLAGS +and GLIB2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GLIB2_CFLAGS +and GLIB2_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GLIB2_CFLAGS=$pkg_cv_GLIB2_CFLAGS + GLIB2_LIBS=$pkg_cv_GLIB2_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPUS" >&5 +$as_echo_n "checking for OPUS... " >&6; } + +if test -n "$OPUS_CFLAGS"; then + pkg_cv_OPUS_CFLAGS="$OPUS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opus >= 0.9.14\""; } >&5 + ($PKG_CONFIG --exists --print-errors "opus >= 0.9.14") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPUS_CFLAGS=`$PKG_CONFIG --cflags "opus >= 0.9.14" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OPUS_LIBS"; then + pkg_cv_OPUS_LIBS="$OPUS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opus >= 0.9.14\""; } >&5 + ($PKG_CONFIG --exists --print-errors "opus >= 0.9.14") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPUS_LIBS=`$PKG_CONFIG --libs "opus >= 0.9.14" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + OPUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "opus >= 0.9.14" 2>&1` + else + OPUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "opus >= 0.9.14" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OPUS_PKG_ERRORS" >&5 + + have_opus=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_opus=no +else + OPUS_CFLAGS=$pkg_cv_OPUS_CFLAGS + OPUS_LIBS=$pkg_cv_OPUS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_opus=yes +fi + + if test "x$have_opus" = "xyes"; then + HAVE_OPUS_TRUE= + HAVE_OPUS_FALSE='#' +else + HAVE_OPUS_TRUE='#' + HAVE_OPUS_FALSE= +fi + + if test "x$have_opus" = "xyes" ; then + +$as_echo "#define HAVE_OPUS 1" >>confdefs.h + + fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5 +$as_echo_n "checking for OPENSSL... " >&6; } + +if test -n "$OPENSSL_CFLAGS"; then + pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OPENSSL_LIBS"; then + pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1` + else + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OPENSSL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (openssl) were not met: + +$OPENSSL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables OPENSSL_CFLAGS +and OPENSSL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables OPENSSL_CFLAGS +and OPENSSL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS + OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + +SPICE_COMMON_CFLAGS='$(PIXMAN_CFLAGS) $(SMARTCARD_CFLAGS) $(CELT051_CFLAGS) $(GLIB2_CFLAGS) $(OPUS_CFLAGS) $(OPENSSL_CFLAGS)' +SPICE_COMMON_LIBS='$(PIXMAN_LIBS) $(CELT051_LIBS) $(GLIB2_LIBS) $(OPUS_LIBS) $(OPENSSL_LIBS)' + + + +# The End! +ac_config_files="$ac_config_files Makefile common/Makefile python_modules/Makefile tests/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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + 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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${HAVE_SMARTCARD_TRUE}" && test -z "${HAVE_SMARTCARD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SMARTCARD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CELT051_TRUE}" && test -z "${HAVE_CELT051_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CELT051\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_OPUS_TRUE}" && test -z "${HAVE_OPUS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_OPUS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by spice-common $as_me noversion, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +spice-common config.status noversion +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + CONFIG_FILES=$CONFIG_FILES" '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + CONFIG_HEADERS=$CONFIG_HEADERS" '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) 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 || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "common/Makefile") CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; + "python_modules/Makefile") CONFIG_FILES="$CONFIG_FILES python_modules/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + 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 '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/spice-common/configure.ac b/spice-common/configure.ac new file mode 100644 index 0000000..f8ff024 --- /dev/null +++ b/spice-common/configure.ac @@ -0,0 +1,62 @@ +AC_PREREQ([2.63]) + +AC_INIT([spice-common], + [noversion], + [spice-devel@lists.freedesktop.org]) + +AC_CONFIG_SRCDIR([common/bitops.h]) +AC_CONFIG_MACRO_DIR([m4]) +AM_CONFIG_HEADER([config.h]) +AC_CONFIG_AUX_DIR([build-aux]) + +# For automake >= 1.12 +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +# Checks for programs +AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip tar-ustar foreign -Wall -Werror]) +AM_MAINTAINER_MODE +AM_SILENT_RULES([yes]) +LT_INIT + +AC_PROG_CC +AC_PROG_CC_C99 +if test "x$ac_cv_prog_cc_c99" = xno; then + AC_MSG_ERROR([C99 compiler is required.]) +fi +AM_PROG_CC_C_O + +SPICE_CHECK_SYSDEPS + +# Checks for libraries +PKG_CHECK_MODULES([PROTOCOL], [spice-protocol >= 0.12.10]) + +SPICE_CHECK_PYTHON_MODULES() + +SPICE_CHECK_PIXMAN +SPICE_CHECK_SMARTCARD +SPICE_CHECK_CELT051 +SPICE_CHECK_GLIB2 +SPICE_CHECK_OPUS +SPICE_CHECK_OPENSSL + +SPICE_COMMON_CFLAGS='$(PIXMAN_CFLAGS) $(SMARTCARD_CFLAGS) $(CELT051_CFLAGS) $(GLIB2_CFLAGS) $(OPUS_CFLAGS) $(OPENSSL_CFLAGS)' +SPICE_COMMON_LIBS='$(PIXMAN_LIBS) $(CELT051_LIBS) $(GLIB2_LIBS) $(OPUS_LIBS) $(OPENSSL_LIBS)' +AC_SUBST(SPICE_COMMON_CFLAGS) +AC_SUBST(SPICE_COMMON_LIBS) + +# The End! +AC_CONFIG_FILES([ + Makefile + common/Makefile + python_modules/Makefile + tests/Makefile +]) + +AH_BOTTOM([ +/* argh.. this is evil */ +#if defined(FIXME_SERVER_SMARTCARD) && defined(USE_SMARTCARD) +%:undef USE_SMARTCARD +#endif +]) + +AC_OUTPUT diff --git a/spice-common/m4/ax_python_module.m4 b/spice-common/m4/ax_python_module.m4 new file mode 100644 index 0000000..3afc404 --- /dev/null +++ b/spice-common/m4/ax_python_module.m4 @@ -0,0 +1,49 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python_module.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON_MODULE(modname[, fatal]) +# +# DESCRIPTION +# +# Checks for Python module. +# +# If fatal is non-empty then absence of a module will trigger an error. +# +# LICENSE +# +# Copyright (c) 2008 Andrew Collier +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE]) +AC_DEFUN([AX_PYTHON_MODULE],[ + if test -z $PYTHON; + then + PYTHON="python" + fi + PYTHON_NAME=`basename $PYTHON` + AC_MSG_CHECKING($PYTHON_NAME module: $1) + $PYTHON -c "import $1" 2>/dev/null + if test $? -eq 0; + then + AC_MSG_RESULT(yes) + eval AS_TR_CPP(HAVE_PYMOD_$1)=yes + else + AC_MSG_RESULT(no) + eval AS_TR_CPP(HAVE_PYMOD_$1)=no + # + if test -n "$2" + then + AC_MSG_ERROR(failed to find required module $1) + exit 1 + fi + fi +]) diff --git a/spice-common/m4/libtool.m4 b/spice-common/m4/libtool.m4 new file mode 100644 index 0000000..a644432 --- /dev/null +++ b/spice-common/m4/libtool.m4 @@ -0,0 +1,8372 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/spice-common/m4/ltoptions.m4 b/spice-common/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/spice-common/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/spice-common/m4/ltsugar.m4 b/spice-common/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/spice-common/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/spice-common/m4/ltversion.m4 b/spice-common/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/spice-common/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/spice-common/m4/lt~obsolete.m4 b/spice-common/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/spice-common/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/spice-common/m4/spice-deps.m4 b/spice-common/m4/spice-deps.m4 new file mode 100644 index 0000000..2e2fcf5 --- /dev/null +++ b/spice-common/m4/spice-deps.m4 @@ -0,0 +1,284 @@ +# For autoconf < 2.63 +m4_ifndef([AS_VAR_APPEND], + AC_DEFUN([AS_VAR_APPEND], $1=$$1$2)) +m4_ifndef([AS_VAR_COPY], + [m4_define([AS_VAR_COPY], + [AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])]) + + +# SPICE_WARNING(warning) +# SPICE_PRINT_MESSAGES +# ---------------------- +# Collect warnings and print them at the end so they are clearly visible. +# --------------------- +AC_DEFUN([SPICE_WARNING],[AS_VAR_APPEND([spice_warnings],["|$1"])]) +AC_DEFUN([SPICE_PRINT_MESSAGES],[ + ac_save_IFS="$IFS" + IFS="|" + for msg in $spice_warnings; do + IFS="$ac_save_IFS" + AS_VAR_IF([msg],[],,[AC_MSG_WARN([$msg]); echo >&2]) + done + IFS="$ac_save_IFS" +]) + + +# SPICE_CHECK_SYSDEPS() +# --------------------- +# Checks for header files and library functions needed by spice-common. +# --------------------- +AC_DEFUN([SPICE_CHECK_SYSDEPS], [ + AC_C_BIGENDIAN + AC_FUNC_ALLOCA + AC_CHECK_HEADERS([arpa/inet.h malloc.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/socket.h unistd.h]) + + # Checks for typedefs, structures, and compiler characteristics + AC_C_INLINE + AC_TYPE_INT16_T + AC_TYPE_INT32_T + AC_TYPE_INT64_T + AC_TYPE_INT8_T + AC_TYPE_PID_T + AC_TYPE_SIZE_T + AC_TYPE_UINT16_T + AC_TYPE_UINT32_T + AC_TYPE_UINT64_T + AC_TYPE_UINT8_T + + # Checks for library functions + # do not check malloc or realloc, since that cannot be cross-compiled checked + AC_FUNC_ERROR_AT_LINE + AC_FUNC_FORK + AC_CHECK_FUNCS([dup2 floor inet_ntoa memmove memset pow sqrt]) +]) + + +# SPICE_CHECK_SMARTCARD +# --------------------- +# Adds a --enable-smartcard switch in order to enable/disable smartcard +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the SMARTCARD_CFLAGS and SMARTCARD_LIBS variables, and +# it will define a USE_SMARTCARD preprocessor symbol as well as a HAVE_SMARTCARD +# Makefile conditional. +#---------------------- +AC_DEFUN([SPICE_CHECK_SMARTCARD], [ + AC_ARG_ENABLE([smartcard], + AS_HELP_STRING([--enable-smartcard=@<:@yes/no/auto@:>@], + [Enable smartcard support @<:@default=auto@:>@]), + [], + [enable_smartcard="auto"]) + + have_smartcard=no + if test "x$enable_smartcard" != "xno"; then + PKG_CHECK_MODULES([SMARTCARD], [libcacard >= 2.5.1], [have_smartcard=yes], [have_smartcard=no]) + if test "x$have_smartcard" = "xno"; then + PKG_CHECK_MODULES([SMARTCARD], [libcacard >= 0.1.2], [have_smartcard=yes have_smartcard_012=yes], [have_smartcard=no]) + fi + if test "x$enable_smartcard" != "xauto" && test "x$have_smartcard" = "xno"; then + AC_MSG_ERROR("Smartcard support requested but libcacard could not be found") + fi + if test "x$have_smartcard_012" = "xyes"; then + AC_DEFINE(USE_SMARTCARD_012, [1], [Define if supporting smartcard proxying without libcacard.h]) + fi + if test "x$have_smartcard" = "xyes"; then + AC_DEFINE(USE_SMARTCARD, [1], [Define if supporting smartcard proxying]) + fi + fi + AM_CONDITIONAL(HAVE_SMARTCARD, test "x$have_smartcard" = "xyes") +]) + + +# SPICE_CHECK_CELT051 +# ------------------- +# Adds a --disable-celt051 switch in order to enable/disable CELT 0.5.1 +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the CELT051_CFLAGS and CELT051_LIBS variables, and +# it will define a HAVE_CELT051 preprocessor symbol as well as a HAVE_CELT051 +# Makefile conditional. +#-------------------- +AC_DEFUN([SPICE_CHECK_CELT051], [ + AC_ARG_ENABLE([celt051], + [ --disable-celt051 Disable celt051 audio codec (enabled by default)],, + [enable_celt051="yes"]) + + if test "x$enable_celt051" = "xyes"; then + PKG_CHECK_MODULES([CELT051], [celt051 >= 0.5.1.1], [have_celt051=yes], [have_celt051=no]) + else + have_celt051=no + fi + + AM_CONDITIONAL([HAVE_CELT051], [test "x$have_celt051" = "xyes"]) + AM_COND_IF([HAVE_CELT051], AC_DEFINE([HAVE_CELT051], 1, [Define if we have celt051 codec])) +]) + + +# SPICE_CHECK_OPUS +# ---------------- +# Check for the availability of Opus. If found, it will return the flags to use +# in the OPUS_CFLAGS and OPUS_LIBS variables, and it will define a +# HAVE_OPUS preprocessor symbol as well as a HAVE_OPUS Makefile conditional. +# ---------------- +AC_DEFUN([SPICE_CHECK_OPUS], [ + PKG_CHECK_MODULES([OPUS], [opus >= 0.9.14], [have_opus=yes], [have_opus=no]) + + AM_CONDITIONAL([HAVE_OPUS], [test "x$have_opus" = "xyes"]) + if test "x$have_opus" = "xyes" ; then + AC_DEFINE([HAVE_OPUS], [1], [Define if we have OPUS]) + fi +]) + + +# SPICE_CHECK_PIXMAN +# ------------------ +# Check for the availability of pixman. If found, it will return the flags to +# use in the PIXMAN_CFLAGS and PIXMAN_LIBS variables. +#------------------- +AC_DEFUN([SPICE_CHECK_PIXMAN], [ + PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.17.7) +]) + + +# SPICE_CHECK_GLIB2 +# ----------------- +# Check for the availability of glib2. If found, it will return the flags to +# use in the GLIB2_CFLAGS and GLIB2_LIBS variables. +#------------------ +AC_DEFUN([SPICE_CHECK_GLIB2], [ + PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.22 gio-2.0 >= 2.22 gthread-2.0 >= 2.22) +]) + +# SPICE_CHECK_PYTHON_MODULES() +# -------------------------- +# Adds a --enable-python-checks configure flags as well as checks for the +# availability of the python modules needed by the python scripts generating +# C code from spice.proto. These checks are not needed when building from +# tarballs so they are disabled by default. +#--------------------------- +AC_DEFUN([SPICE_CHECK_PYTHON_MODULES], [ + AM_PATH_PYTHON + AC_ARG_ENABLE([python-checks], + AS_HELP_STRING([--enable-python-checks=@<:@yes/no@:>@], + [Enable checks for Python modules needed to build from git @<:@default=no@:>@]), + [], + [enable_python_checks="no"]) + if test "x$enable_python_checks" != "xno"; then + AX_PYTHON_MODULE([six], [1]) + AX_PYTHON_MODULE([pyparsing], [1]) + fi +]) + + +# SPICE_CHECK_LZ4 +# --------------- +# Adds a --enable-lz4 switch in order to enable/disable LZ4 compression +# support, and checks if the needed libraries are available. If found, it will +# return the flags to use in the LZ4_CFLAGS and LZ4_LIBS variables, and +# it will define a USE_LZ4 preprocessor symbol. +# conditional. +# --------------- +AC_DEFUN([SPICE_CHECK_LZ4], [ + AC_ARG_ENABLE([lz4], + AS_HELP_STRING([--enable-lz4=@<:@yes/no/auto@:>@], + [Enable LZ4 compression support @<:@default=auto@:>@]), + [], + [enable_lz4="auto"]) + + if test "x$enable_lz4" != "xno"; then + PKG_CHECK_MODULES([LZ4], [liblz4], + [enable_lz4=yes + AC_DEFINE(USE_LZ4, [1], [Define to build with lz4 support]) + ], + [if test "x$enable_lz4" = "xyes"; then + AC_MSG_ERROR([lz4 support requested but liblz4 could not be found]) + fi] + ) + fi +]) + + +# SPICE_CHECK_GSTREAMER(VAR, version, packages-to-check-for, [action-if-found, [action-if-not-found]]) +# --------------------- +# Checks whether the specified GStreamer modules are present and sets the +# corresponding autoconf variables and preprocessor definitions. +# --------------------- +AC_DEFUN([SPICE_CHECK_GSTREAMER], [ + AS_VAR_PUSHDEF([have_gst],[have_]m4_tolower([$1]))dnl + AS_VAR_PUSHDEF([gst_inspect],[GST_INSPECT_$2])dnl + PKG_CHECK_MODULES([$1], [$3], + [have_gst="yes" + AC_SUBST(AS_TR_SH([[$1]_CFLAGS])) + AC_SUBST(AS_TR_SH([[$1]_LIBS])) + AS_VAR_APPEND([SPICE_REQUIRES], [" $3"]) + AC_DEFINE(AS_TR_SH([HAVE_$1]), [1], [Define if supporting GStreamer $2]) + AC_PATH_PROG(gst_inspect, gst-inspect-$2) + AS_IF([test "x$gst_inspect" = x], + SPICE_WARNING([Cannot verify that the required runtime GStreamer $2 elements are present because gst-inspect-$2 is missing])) + $4], + [have_gst="no" + $5]) + AS_VAR_POPDEF([gst_inspect])dnl + AS_VAR_POPDEF([have_gst])dnl +]) + +# SPICE_CHECK_GSTREAMER_ELEMENTS(gst-inspect, package, elements-to-check-for) +# --------------------- +# Checks that the specified GStreamer elements are installed. If not it +# issues a warning and sets missing_gstreamer_elements. +# --------------------- +AC_DEFUN([SPICE_CHECK_GSTREAMER_ELEMENTS], [ +AS_IF([test "x$1" != x], + [missing="" + for element in $3 + do + AS_VAR_PUSHDEF([cache_var],[spice_cv_prog_${1}_${element}])dnl + AC_CACHE_CHECK([for the $element GStreamer element], cache_var, + [found=no + "$1" $element >/dev/null 2>/dev/null && found=yes + eval "cache_var=$found"]) + AS_VAR_COPY(res, cache_var) + AS_IF([test "x$res" = "xno"], [missing="$missing $element"]) + AS_VAR_POPDEF([cache_var])dnl + done + AS_IF([test "x$missing" != x], + [SPICE_WARNING([The$missing GStreamer element(s) are missing. You should be able to find them in the $2 package.]) + missing_gstreamer_elements="yes"], + [test "x$missing_gstreamer_elements" = x], + [missing_gstreamer_elements="no"]) + ]) +]) + +# SPICE_CHECK_SASL +# ---------------- +# Adds a --with-sasl switch to allow using SASL for authentication. +# Checks whether the required library is available. If it is present, +# it will return the flags to use in SASL_CFLAGS and SASL_LIBS variables, +# and it will define a have_sasl configure variable and a HAVE_SASL preprocessor +# symbol. +# ---------------- +AC_DEFUN([SPICE_CHECK_SASL], [ + AC_ARG_WITH([sasl], + [AS_HELP_STRING([--with-sasl=@<:@yes/no/auto@:>@], + [use cyrus SASL for authentication @<:@default=auto@:>@])], + [], + [with_sasl="auto"]) + + have_sasl=no + if test "x$with_sasl" != "xno"; then + PKG_CHECK_MODULES([SASL], [libsasl2], [have_sasl=yes],[have_sasl=no]) + if test "x$have_sasl" = "xno" && test "x$with_sasl" = "xyes"; then + AC_MSG_ERROR([Cyrus SASL support requested but libsasl2 could not be found]) + fi + if test "x$have_sasl" = "xyes"; then + AC_DEFINE([HAVE_SASL], 1, [whether Cyrus SASL is available for authentication]) + fi + fi +]) + +# SPICE_CHECK_OPENSSL +# ----------------- +# Check for the availability of openssl. If found, it will return the flags to +# use in the OPENSSL_CFLAGS and OPENSSL_LIBS variables. +#------------------ +AC_DEFUN([SPICE_CHECK_OPENSSL], [ + PKG_CHECK_MODULES(OPENSSL, openssl) +]) diff --git a/spice-common/python_modules/Makefile.am b/spice-common/python_modules/Makefile.am new file mode 100644 index 0000000..50e1a71 --- /dev/null +++ b/spice-common/python_modules/Makefile.am @@ -0,0 +1,16 @@ +NULL = + +PYTHON_MODULES = \ + __init__.py \ + codegen.py \ + demarshal.py \ + marshal.py \ + ptypes.py \ + spice_parser.py \ + $(NULL) + +EXTRA_DIST = $(PYTHON_MODULES) + +DISTCLEANFILES = *.pyc + +-include $(top_srcdir)/git.mk diff --git a/spice-common/python_modules/Makefile.in b/spice-common/python_modules/Makefile.in new file mode 100644 index 0000000..7a7a578 --- /dev/null +++ b/spice-common/python_modules/Makefile.in @@ -0,0 +1,480 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = python_modules +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CELT051_CFLAGS = @CELT051_CFLAGS@ +CELT051_LIBS = @CELT051_LIBS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPUS_CFLAGS = @OPUS_CFLAGS@ +OPUS_LIBS = @OPUS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOCOL_CFLAGS = @PROTOCOL_CFLAGS@ +PROTOCOL_LIBS = @PROTOCOL_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_COMMON_CFLAGS = @SPICE_COMMON_CFLAGS@ +SPICE_COMMON_LIBS = @SPICE_COMMON_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +PYTHON_MODULES = \ + __init__.py \ + codegen.py \ + demarshal.py \ + marshal.py \ + ptypes.py \ + spice_parser.py \ + $(NULL) + +EXTRA_DIST = $(PYTHON_MODULES) +DISTCLEANFILES = *.pyc +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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python_modules/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign python_modules/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +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 + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -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: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/spice-common/python_modules/__init__.py b/spice-common/python_modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/spice-common/python_modules/codegen.py b/spice-common/python_modules/codegen.py new file mode 100644 index 0000000..f7a2048 --- /dev/null +++ b/spice-common/python_modules/codegen.py @@ -0,0 +1,380 @@ + +import six +from io import StringIO + +def camel_to_underscores(s, upper = False): + res = "" + for i in range(len(s)): + c = s[i] + if i > 0 and c.isupper(): + res = res + "_" + if upper: + res = res + c.upper() + else: + res = res + c.lower() + return res + +def underscores_to_camel(s): + res = "" + do_upper = True + for i in range(len(s)): + c = s[i] + if c == "_": + do_upper = True + else: + if do_upper: + res = res + c.upper() + else: + res = res + c + do_upper = False + return res + +proto_prefix = "Temp" + +def set_prefix(prefix): + global proto_prefix + global proto_prefix_upper + global proto_prefix_lower + proto_prefix = prefix + proto_prefix_upper = prefix.upper() + proto_prefix_lower = prefix.lower() + +def prefix_underscore_upper(*args): + s = proto_prefix_upper + for arg in args: + s = s + "_" + arg + return s + +def prefix_underscore_lower(*args): + s = proto_prefix_lower + for arg in args: + s = s + "_" + arg + return s + +def prefix_camel(*args): + s = proto_prefix + for arg in args: + s = s + underscores_to_camel(arg) + return s + +def increment_identifier(idf): + v = idf[-1:] + if v.isdigit(): + return idf[:-1] + str(int(v) + 1) + return idf + "2" + +def sum_array(array): + if len(array) == 0: + return 0 + return " + ".join(array) + +class CodeWriter: + def __init__(self): + self.out = StringIO() + self.contents = [self.out] + self.indentation = 0 + self.at_line_start = True + self.indexes = ["i", "j", "k", "ii", "jj", "kk"] + self.current_index = 0 + self.generated = {} + self.vars = [] + self.has_error_check = False + self.options = {} + self.function_helper_writer = None + self.index_type = 'uint32_t' + + def set_option(self, opt, value = True): + self.options[opt] = value + + def has_option(self, opt): + return opt in self.options + + def set_is_generated(self, kind, name): + if kind not in self.generated: + v = {} + self.generated[kind] = v + else: + v = self.generated[kind] + v[name] = 1 + + def is_generated(self, kind, name): + if kind not in self.generated: + return False + v = self.generated[kind] + return name in v + + def getvalue(self): + strs = [writer.getvalue() for writer in self.contents] + return "".join(strs) + + def get_subwriter(self): + writer = CodeWriter() + self.contents.append(writer) + self.out = StringIO() + self.contents.append(self.out) + writer.indentation = self.indentation + writer.at_line_start = self.at_line_start + writer.index_type = self.index_type + writer.generated = self.generated + writer.options = self.options + writer.public_prefix = self.public_prefix + + return writer + + def write(self, s): + # Ensure its a unicode string + if six.PY3: + s = str(s) + else: + s = unicode(s) + + if len(s) == 0: + return + + if self.at_line_start: + self.out.write(u" " * self.indentation) + self.at_line_start = False + self.out.write(s) + return self + + def newline(self): + self.out.write(u"\n") + self.at_line_start = True + return self + + def writeln(self, s): + self.write(s) + self.newline() + return self + + def label(self, s): + self.indentation = self.indentation - 1 + self.write(s + ":") + self.indentation = self.indentation + 1 + self.newline() + + def statement(self, s): + self.write(s) + self.write(";") + self.newline() + return self + + def assign(self, var, val): + self.write("%s = %s" % (var, val)) + self.write(";") + self.newline() + return self + + def increment(self, var, val): + self.write("%s += %s" % (var, val)) + self.write(";") + self.newline() + return self + + def comment(self, str): + self.write("/* " + str + " */") + return self + + def todo(self, str): + self.comment("TODO: *** %s ***" % str).newline() + return self + + def error_check(self, check, label = "error"): + self.has_error_check = True + with self.block("if (SPICE_UNLIKELY(%s))" % check): + if self.has_option("print_error"): + self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check) + if self.has_option("assert_on_error"): + self.statement("assert(0)") + self.statement("goto %s" % label) + + def indent(self): + self.indentation += 4 + + def unindent(self): + self.indentation -= 4 + if self.indentation < 0: + self.indentation = 0 + + def begin_block(self, prefix= "", comment = ""): + if len(prefix) > 0: + self.write(prefix) + if self.at_line_start: + self.write("{") + else: + self.write(" {") + if len(comment) > 0: + self.write(" ") + self.comment(comment) + self.newline() + self.indent() + + def end_block(self, semicolon=False, newline=True): + self.unindent() + if self.at_line_start: + self.write("}") + else: + self.write(" }") + if semicolon: + self.write(";") + if newline: + self.newline() + + class Block: + def __init__(self, writer, semicolon, newline): + self.writer = writer + self.semicolon = semicolon + self.newline = newline + + def __enter__(self): + return self.writer.get_subwriter() + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.end_block(self.semicolon, self.newline) + + class PartialBlock: + def __init__(self, writer, scope, semicolon, newline): + self.writer = writer + self.scope = scope + self.semicolon = semicolon + self.newline = newline + + def __enter__(self): + return self.scope + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.end_block(self.semicolon, self.newline) + + class NoBlock: + def __init__(self, scope): + self.scope = scope + + def __enter__(self): + return self.scope + + def __exit__(self, exc_type, exc_value, traceback): + pass + + def block(self, prefix= "", comment = "", semicolon=False, newline=True): + self.begin_block(prefix, comment) + return self.Block(self, semicolon, newline) + + def partial_block(self, scope, semicolon=False, newline=True): + return self.PartialBlock(self, scope, semicolon, newline) + + def no_block(self, scope): + return self.NoBlock(scope) + + def optional_block(self, scope): + if scope != None: + return self.NoBlock(scope) + return self.block() + + def for_loop(self, index, limit): + return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index)) + + def while_loop(self, expr): + return self.block("while (%s)" % (expr)) + + def if_block(self, check, elseif=False, newline=True): + s = "if (%s)" % (check) + if elseif: + s = " else " + s + self.begin_block(s, "") + return self.Block(self, False, newline) + + def variable_defined(self, name): + for n in self.vars: + if n == name: + return True + return False + + def variable_def(self, ctype, *names): + for n in names: + # Strip away initialization + i = n.find("=") + if i != -1: + n = n[0:i] + self.vars.append(n.strip()) + # only add space for non-pointer types + if ctype[-1] == "*": + ctype = ctype[:-1].rstrip() + self.writeln("%s *%s;"%(ctype, ", *".join(names))) + else: + self.writeln("%s %s;"%(ctype, ", ".join(names))) + return self + + def function_helper(self): + if self.function_helper_writer != None: + writer = self.function_helper_writer.get_subwriter() + self.function_helper_writer.newline() + else: + writer = self.get_subwriter() + return writer + + def function(self, name, return_type, args, static = False): + self.has_error_check = False + self.function_helper_writer = self.get_subwriter() + if static: + self.write("static ") + self.write(return_type) + self.write(" %s(%s)"% (name, args)).newline() + self.begin_block() + self.function_variables_writer = self.get_subwriter() + self.function_variables = {} + return self.function_variables_writer + + def macro(self, name, args, define): + self.write("#define %s(%s) %s" % (name, args, define)).newline() + + def ifdef(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#ifdef %s" % (name)).newline() + self.indentation = indentation + + def ifdef_else(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#else /* %s */" % (name)).newline() + self.indentation = indentation + + def endif(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#endif /* %s */" % (name)).newline() + self.indentation = indentation + + def add_function_variable(self, ctype, name): + if name in self.function_variables: + assert(self.function_variables[name] == ctype) + else: + self.function_variables[name] = ctype + self.function_variables_writer.variable_def(ctype, name) + + def pop_index(self): + index = self.indexes[self.current_index] + self.current_index = self.current_index + 1 + self.add_function_variable(self.index_type, index) + return index + + def push_index(self): + assert self.current_index > 0 + self.current_index = self.current_index - 1 + + class Index: + def __init__(self, writer, val): + self.writer = writer + self.val = val + + def __enter__(self): + return self.val + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.push_index() + + def index(self, no_block = False): + if no_block: + return self.no_block(None) + val = self.pop_index() + return self.Index(self, val) diff --git a/spice-common/python_modules/demarshal.py b/spice-common/python_modules/demarshal.py new file mode 100644 index 0000000..2252f37 --- /dev/null +++ b/spice-common/python_modules/demarshal.py @@ -0,0 +1,1274 @@ + +from . import ptypes +from . import codegen + +# The handling of sizes is somewhat complex, as there are several types of size: +# * nw_size +# This is the network size, i.e. the number of bytes on the network +# +# * mem_size +# The total amount of memory used for the representation of something inside +# spice. This is generally sizeof(C struct), but can be larger if for instance +# the type has a variable size array at the end or has a pointer in it that +# points to another data chunk (which will be allocated after the main +# data chunk). This is essentially how much memory you need to allocate to +# contain the data type. +# +# * extra_size +# This is the size of anything that is not part of the containing structure. +# For instance, a primitive (say uint32_t) member has no extra size, because +# when allocating its part of the sizeof(MessageStructType) struct. However +# a variable array can be places at the end of a structure (@end) and its +# size is then extra_size. Note that this extra_size is included in the +# mem_size of the enclosing struct, and even if you request the mem_size +# of the array itself. However, extra_size is typically not requested +# when the full mem_size is also requested. +# +# extra sizes come in two flavours. contains_extra_size means that the item +# has a normal presence in the parent container, but has some additional +# extra_size it references. For instance via a pointer somewhere in it. +# There is also is_extra_size(). This indicates that the whole elements +# "normal" mem size should be considered extra size for the container, so +# when computing the parent mem_size you should add the mem_size of this +# part as extra_size + +def write_parser_helpers(writer): + if writer.is_generated("helper", "demarshaller"): + return + + writer.set_is_generated("helper", "demarshaller") + + writer = writer.function_helper() + + writer.writeln("#ifdef WORDS_BIGENDIAN") + for size in [8, 16, 32, 64]: + for sign in ["", "u"]: + utype = "uint%d" % (size) + type = "%sint%d" % (sign, size) + swap = "SPICE_BYTESWAP%d" % size + if size == 8: + writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type) + writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type)) + else: + writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr))))" % (type, swap, utype)) + writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype)) + writer.writeln("#else") + for size in [8, 16, 32, 64]: + for sign in ["", "u"]: + type = "%sint%d" % (sign, size) + writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type) + writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type) + writer.writeln("#endif") + + for size in [8, 16, 32, 64]: + for sign in ["", "u"]: + writer.newline() + type = "%sint%d" % (sign, size) + ctype = "%s_t" % type + scope = writer.function("SPICE_GNUC_UNUSED consume_%s" % type, ctype, "uint8_t **ptr", True) + scope.variable_def(ctype, "val") + writer.assign("val", "read_%s(*ptr)" % type) + writer.increment("*ptr", size // 8) + writer.statement("return val") + writer.end_block() + + writer.function("SPICE_GNUC_UNUSED consume_fd", "int", "uint8_t **ptr", True) + writer.statement("return -1") + writer.end_block() + + writer.newline() + writer.statement("typedef struct PointerInfo PointerInfo") + writer.statement("typedef void (*message_destructor_t)(uint8_t *message)") + writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)") + writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)") + writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)") + + writer.newline() + writer.begin_block("struct PointerInfo") + writer.variable_def("uint64_t", "offset") + writer.variable_def("parse_func_t", "parse") + writer.variable_def("void **", "dest") + writer.variable_def("uint32_t", "nelements") + writer.end_block(semicolon=True) + +def write_read_primitive(writer, start, container, name, scope): + m = container.lookup_member(name) + assert(m.is_primitive()) + writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size")) + writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size()) + + var = "%s__value" % (name.replace(".", "_")) + if not scope.variable_defined(var): + scope.variable_def(m.member_type.c_type(), var) + writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type())) + return var + +def write_write_primitive(writer, start, container, name, val): + m = container.lookup_member(name) + assert(m.is_primitive()) + writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size")) + + var = "%s__value" % (name) + writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val)) + return var + +def write_read_primitive_item(writer, item, scope): + assert(item.type.is_primitive()) + writer.assign("pos", item.get_position()) + writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size()) + var = "%s__value" % (item.subprefix.replace(".", "_")) + scope.variable_def(item.type.c_type(), var) + writer.assign(var, "read_%s(pos)" % (item.type.primitive_type())) + return var + +class ItemInfo: + def __init__(self, type, prefix, position): + self.type = type + self.prefix = prefix + self.subprefix = prefix + self.position = position + self.member = None + + def nw_size(self): + return self.prefix + "__nw_size" + + def mem_size(self): + return self.prefix + "__mem_size" + + def extra_size(self): + return self.prefix + "__extra_size" + + def get_position(self): + return self.position + +class MemberItemInfo(ItemInfo): + def __init__(self, member, mprefix, container, start): + if not member.is_switch(): + self.type = member.member_type + self.prefix = member.name + if mprefix: + mprefix = mprefix + "_" + self.prefix = mprefix + self.prefix + self.subprefix = member.name + self.position = "(%s + %s)" % (start, container.get_nw_offset(member, mprefix or "", "__nw_size")) + self.member = member + +def write_validate_switch_member(writer, mprefix, container, switch_member, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + var = container.lookup_member(switch_member.variable) + var_type = var.member_type + + v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope) + + item = MemberItemInfo(switch_member, mprefix, container, start) + + first = True + for c in switch_member.cases: + check = c.get_check(v, var_type) + m = c.member + with writer.if_block(check, not first, False) as if_scope: + item.type = c.member.member_type + item.subprefix = item.prefix + "_" + m.name + item.member = c.member + + all_as_extra_size = m.is_extra_size() and want_extra_size + if not want_mem_size and all_as_extra_size and not scope.variable_defined(item.mem_size()): + scope.variable_def("uint32_t", item.mem_size()) + + sub_want_mem_size = want_mem_size or all_as_extra_size + sub_want_extra_size = want_extra_size and not all_as_extra_size + + write_validate_item(writer, container, item, if_scope, scope, start, + want_nw_size, sub_want_mem_size, sub_want_extra_size) + + if all_as_extra_size: + writer.assign(item.extra_size(), item.mem_size()) + + first = False + + with writer.block(" else"): + if want_nw_size: + writer.assign(item.nw_size(), 0) + if want_mem_size: + writer.assign(item.mem_size(), 0) + if want_extra_size: + writer.assign(item.extra_size(), 0) + + writer.newline() + +def write_validate_struct_function(writer, struct): + validate_function = "validate_%s" % struct.c_type() + if writer.is_generated("validator", validate_function): + return validate_function + + writer.set_is_generated("validator", validate_function) + writer = writer.function_helper() + scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, SPICE_GNUC_UNUSED int minor") + scope.variable_def("uint8_t *", "start = message_start + offset") + scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") + scope.variable_def("size_t", "mem_size", "nw_size") + num_pointers = struct.get_num_pointers() + if num_pointers != 0: + scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") + + writer.newline() + with writer.if_block("offset == 0"): + writer.statement("return 0") + + writer.newline() + writer.error_check("start >= message_end") + + writer.newline() + write_validate_container(writer, None, struct, "start", scope, True, True, False) + + writer.newline() + writer.comment("Check if struct fits in reported side").newline() + writer.error_check("start + nw_size > message_end") + + writer.statement("return mem_size") + + writer.newline() + writer.label("error") + writer.statement("return -1") + + writer.end_block() + + return validate_function + +def write_validate_pointer_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + if want_nw_size: + writer.assign(item.nw_size(), item.type.get_fixed_nw_size()) + + if want_mem_size or want_extra_size: + target_type = item.type.target_type + + v = write_read_primitive_item(writer, item, scope) + if item.type.has_attr("nonnull"): + writer.error_check("%s == 0" % v) + + # pointer target is struct, or array of primitives + # if array, need no function check + + if target_type.is_array(): + writer.error_check("message_start + %s >= message_end" % v) + + + assert target_type.element_type.is_primitive() + + array_item = ItemInfo(target_type, "%s__array" % item.prefix, start) + scope.variable_def("uint32_t", array_item.nw_size()) + # don't create a variable that isn't used, fixes -Werror=unused-but-set-variable + need_mem_size = want_mem_size or ( + want_extra_size and not item.member.has_attr("chunk") + and not target_type.is_cstring_length()) + if need_mem_size: + scope.variable_def("uint32_t", array_item.mem_size()) + if target_type.is_cstring_length(): + writer.assign(array_item.nw_size(), "spice_strnlen((char *)message_start + %s, message_end - (message_start + %s))" % (v, v)) + writer.error_check("*(message_start + %s + %s) != 0" % (v, array_item.nw_size())) + else: + write_validate_array_item(writer, container, array_item, scope, parent_scope, start, + True, want_mem_size=need_mem_size, want_extra_size=False) + writer.error_check("message_start + %s + %s > message_end" % (v, array_item.nw_size())) + + if want_extra_size: + if item.member and item.member.has_attr("chunk"): + writer.assign(item.extra_size(), "sizeof(SpiceChunks) + sizeof(SpiceChunk)") + elif item.member and item.member.has_attr("nocopy"): + writer.comment("@nocopy, so no extra size").newline() + writer.assign(item.extra_size(), 0) + elif target_type.element_type.get_fixed_nw_size == 1: + writer.assign(item.extra_size(), array_item.mem_size()) + # If not bytes or zero, add padding needed for alignment + else: + writer.assign(item.extra_size(), "%s + /* for alignment */ 3" % array_item.mem_size()) + if want_mem_size: + writer.assign(item.mem_size(), "sizeof(void *) + %s" % array_item.mem_size()) + + elif target_type.is_struct(): + validate_function = write_validate_struct_function(writer, target_type) + writer.assign("ptr_size", "%s(message_start, message_end, %s, minor)" % (validate_function, v)) + writer.error_check("ptr_size < 0") + + if want_extra_size: + writer.assign(item.extra_size(), "ptr_size + /* for alignment */ 3") + if want_mem_size: + writer.assign(item.mem_size(), "sizeof(void *) + ptr_size") + else: + raise NotImplementedError("pointer to unsupported type %s" % target_type) + + +def write_validate_array_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + array = item.type + is_byte_size = False + element_type = array.element_type + if array.is_bytes_length(): + nelements = "%s__nbytes" %(item.prefix) + real_nelements = "%s__nelements" %(item.prefix) + if not parent_scope.variable_defined(real_nelements): + parent_scope.variable_def("uint32_t", real_nelements) + else: + nelements = "%s__nelements" %(item.prefix) + if not parent_scope.variable_defined(nelements): + parent_scope.variable_def("uint32_t", nelements) + + if array.is_constant_length(): + writer.assign(nelements, array.size) + elif array.is_remaining_length(): + if element_type.is_fixed_nw_size(): + if element_type.get_fixed_nw_size() == 1: + writer.assign(nelements, "message_end - %s" % item.get_position()) + else: + writer.assign(nelements, "(message_end - %s) / (%s)" %(item.get_position(), element_type.get_fixed_nw_size())) + else: + raise NotImplementedError("TODO array[] of dynamic element size not done yet") + elif array.is_identifier_length(): + v = write_read_primitive(writer, start, container, array.size, scope) + writer.assign(nelements, v) + elif array.is_image_size_length(): + bpp = array.size[1] + width = array.size[2] + rows = array.size[3] + width_v = write_read_primitive(writer, start, container, width, scope) + rows_v = write_read_primitive(writer, start, container, rows, scope) + # TODO: Handle multiplication overflow + if bpp == 8: + writer.assign(nelements, "%s * %s" % (width_v, rows_v)) + elif bpp == 1: + writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v)) + else: + writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v)) + elif array.is_bytes_length(): + is_byte_size = True + v = write_read_primitive(writer, start, container, array.size[1], scope) + writer.assign(nelements, v) + writer.assign(real_nelements, 0) + elif array.is_cstring_length(): + writer.todo("cstring array size type not handled yet") + else: + writer.todo("array size type not handled yet") + + writer.newline() + + nw_size = item.nw_size() + mem_size = item.mem_size() + extra_size = item.extra_size() + + if is_byte_size and want_nw_size: + writer.assign(nw_size, nelements) + want_nw_size = False + + if element_type.is_fixed_nw_size() and want_nw_size: + element_size = element_type.get_fixed_nw_size() + # TODO: Overflow check the multiplication + if element_size == 1: + writer.assign(nw_size, nelements) + else: + writer.assign(nw_size, "(%s) * %s" % (element_size, nelements)) + want_nw_size = False + + if array.has_attr("as_ptr") and want_mem_size: + writer.assign(mem_size, "sizeof(void *)") + want_mem_size = False + + if array.has_attr("chunk"): + if want_mem_size: + writer.assign(extra_size, "sizeof(SpiceChunks *)") + want_mem_size = False + if want_extra_size: + writer.assign(extra_size, "sizeof(SpiceChunks) + sizeof(SpiceChunk)") + want_extra_size = False + + if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size: + # TODO: Overflow check the multiplication + if array.has_attr("ptr_array"): + writer.assign(mem_size, "sizeof(void *) + SPICE_ALIGN(%s * %s, 4)" % (element_type.sizeof(), nelements)) + else: + writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements)) + want_mem_size = False + + if not element_type.contains_extra_size() and want_extra_size: + writer.assign(extra_size, 0) + want_extra_size = False + + if not (want_mem_size or want_nw_size or want_extra_size): + return + + start2 = codegen.increment_identifier(start) + scope.variable_def("uint8_t *", "%s = %s" % (start2, item.get_position())) + if is_byte_size: + start2_end = "%s_array_end" % start2 + scope.variable_def("uint8_t *", start2_end) + + element_item = ItemInfo(element_type, "%s__element" % item.prefix, start2) + + element_nw_size = element_item.nw_size() + element_mem_size = element_item.mem_size() + element_extra_size = element_item.extra_size() + scope.variable_def("uint32_t", element_nw_size) + scope.variable_def("uint32_t", element_mem_size) + if want_extra_size: + scope.variable_def("uint32_t", element_extra_size) + + if want_nw_size: + writer.assign(nw_size, 0) + if want_mem_size: + writer.assign(mem_size, 0) + if want_extra_size: + writer.assign(extra_size, 0) + + want_element_nw_size = want_nw_size + if element_type.is_fixed_nw_size(): + start_increment = element_type.get_fixed_nw_size() + else: + want_element_nw_size = True + start_increment = element_nw_size + + if is_byte_size: + writer.assign(start2_end, "%s + %s" % (start2, nelements)) + + with writer.index(no_block = is_byte_size) as index: + with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope: + if is_byte_size: + writer.increment(real_nelements, 1) + write_validate_item(writer, container, element_item, scope, parent_scope, start2, + want_element_nw_size, want_mem_size, want_extra_size) + + if want_nw_size: + writer.increment(nw_size, element_nw_size) + if want_mem_size: + if array.has_attr("ptr_array"): + writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size) + else: + writer.increment(mem_size, element_mem_size) + if want_extra_size: + writer.increment(extra_size, element_extra_size) + + writer.increment(start2, start_increment) + if is_byte_size: + writer.error_check("%s != %s" % (start2, start2_end)) + write_write_primitive(writer, start, container, array.size[1], real_nelements) + +def write_validate_struct_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + struct = item.type + start2 = codegen.increment_identifier(start) + scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", start2 + " = %s" % (item.get_position())) + + write_validate_container(writer, item.prefix, struct, start2, scope, want_nw_size, want_mem_size, want_extra_size) + +def write_validate_primitive_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + if want_nw_size: + nw_size = item.nw_size() + writer.assign(nw_size, item.type.get_fixed_nw_size()) + if want_mem_size: + mem_size = item.mem_size() + writer.assign(mem_size, item.type.sizeof()) + if want_extra_size: + writer.assign(item.extra_size(), 0) + +def write_validate_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + if item.member and item.member.has_attr("to_ptr"): + want_nw_size = True + if item.type.is_pointer(): + write_validate_pointer_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + elif item.type.is_array(): + write_validate_array_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + elif item.type.is_struct(): + write_validate_struct_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + elif item.type.is_primitive(): + write_validate_primitive_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + else: + writer.todo("Implement validation of %s" % item.type) + + if item.member and item.member.has_attr("to_ptr"): + saved_size = "%s__saved_size" % item.member.name + writer.add_function_variable("uint32_t", saved_size + " = 0") + writer.assign(saved_size, item.nw_size()) + +def write_validate_member(writer, mprefix, container, member, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size): + if member.has_attr("virtual"): + return + + if member.has_minor_attr(): + prefix = "if (minor >= %s)" % (member.get_minor_attr()) + newline = False + else: + prefix = "" + newline = True + item = MemberItemInfo(member, mprefix, container, start) + with writer.block(prefix, newline=newline, comment=member.name) as scope: + if member.is_switch(): + write_validate_switch_member(writer, mprefix, container, member, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + else: + write_validate_item(writer, container, item, scope, parent_scope, start, + want_nw_size, want_mem_size, want_extra_size) + + if member.has_minor_attr(): + with writer.block(" else", comment = "minor < %s" % (member.get_minor_attr())): + if member.is_array(): + nelements = "%s__nelements" %(item.prefix) + writer.assign(nelements, 0) + if want_nw_size: + writer.assign(item.nw_size(), 0) + + if want_mem_size: + if member.is_fixed_sizeof(): + writer.assign(item.mem_size(), member.sizeof()) + elif member.is_array(): + writer.assign(item.mem_size(), 0) + else: + raise NotImplementedError("TODO minor check for non-constant items") + + assert not want_extra_size + +def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size): + def prefix_m(prefix, m): + name = m.name + if prefix: + name = prefix + "_" + name + return name + + for m in container.members: + sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size() + sub_want_mem_size = m.is_extra_size() and want_mem_size + sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size() + defs = ["size_t"] + name = prefix_m(prefix, m) + if sub_want_nw_size: + + defs.append (name + "__nw_size") + if sub_want_mem_size: + defs.append (name + "__mem_size") + if sub_want_extra_size: + defs.append (name + "__extra_size") + + if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size: + parent_scope.variable_def(*defs) + write_validate_member(writer, prefix, container, m, parent_scope, start, + sub_want_nw_size, sub_want_mem_size, sub_want_extra_size) + writer.newline() + + if want_nw_size: + if prefix: + nw_size = prefix + "__nw_size" + else: + nw_size = "nw_size" + + size = 0 + for m in container.members: + if m.is_fixed_nw_size(): + size = size + m.get_fixed_nw_size() + + nm_sum = str(size) + for m in container.members: + name = prefix_m(prefix, m) + if not m.is_fixed_nw_size(): + nm_sum = nm_sum + " + " + name + "__nw_size" + + writer.assign(nw_size, nm_sum) + + if want_mem_size: + if prefix: + mem_size = prefix + "__mem_size" + else: + mem_size = "mem_size" + + mem_sum = container.sizeof() + for m in container.members: + name = prefix_m(prefix, m) + if m.is_extra_size(): + mem_sum = mem_sum + " + " + name + "__mem_size" + elif m.contains_extra_size(): + mem_sum = mem_sum + " + " + name + "__extra_size" + + writer.assign(mem_size, mem_sum) + + if want_extra_size: + if prefix: + extra_size = prefix + "__extra_size" + else: + extra_size = "extra_size" + + extra_sum = [] + for m in container.members: + name = prefix_m(prefix, m) + if m.is_extra_size(): + extra_sum.append(name + "__mem_size") + elif m.contains_extra_size(): + extra_sum.append(name + "__extra_size") + writer.assign(extra_size, codegen.sum_array(extra_sum)) + +class DemarshallingDestination: + def __init__(self): + pass + + def child_at_end(self, writer, t): + return RootDemarshallingDestination(self, t.c_type(), t.sizeof()) + + def child_sub(self, member): + return SubDemarshallingDestination(self, member) + + def declare(self, writer): + return writer.optional_block(self.reuse_scope) + + def is_toplevel(self): + return self.parent_dest == None and not self.is_helper + +class RootDemarshallingDestination(DemarshallingDestination): + def __init__(self, parent_dest, c_type, sizeof, pointer = None): + self.is_helper = False + self.reuse_scope = None + self.parent_dest = parent_dest + if parent_dest: + self.base_var = codegen.increment_identifier(parent_dest.base_var) + else: + self.base_var = "out" + self.c_type = c_type + self.sizeof = sizeof + self.pointer = pointer # None == at "end" + + def get_ref(self, member): + return self.base_var + "->" + member + + def declare(self, writer): + if self.reuse_scope: + scope = self.reuse_scope + else: + writer.begin_block() + scope = writer.get_subwriter() + + scope.variable_def(self.c_type + " *", self.base_var) + if not self.reuse_scope: + scope.newline() + + if self.pointer: + writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer)) + else: + writer.assign(self.base_var, "(%s *)end" % (self.c_type)) + writer.increment("end", self.sizeof) + writer.newline() + + if self.reuse_scope: + return writer.no_block(self.reuse_scope) + else: + return writer.partial_block(scope) + +class SubDemarshallingDestination(DemarshallingDestination): + def __init__(self, parent_dest, member): + self.reuse_scope = None + self.parent_dest = parent_dest + self.base_var = parent_dest.base_var + self.member = member + self.is_helper = False + + def get_ref(self, member): + return self.parent_dest.get_ref(self.member) + "." + member + +# Note: during parsing, byte_size types have been converted to count during validation +def read_array_len(writer, prefix, array, dest, scope, is_ptr): + if is_ptr: + nelements = "%s__array__nelements" % prefix + else: + nelements = "%s__nelements" % prefix + if dest.is_toplevel() and scope.variable_defined(nelements): + return nelements # Already there for toplevel, need not recalculate + element_type = array.element_type + scope.variable_def("uint32_t", nelements) + if array.is_constant_length(): + writer.assign(nelements, array.size) + elif array.is_identifier_length(): + writer.assign(nelements, dest.get_ref(array.size)) + elif array.is_remaining_length(): + if element_type.is_fixed_nw_size(): + writer.assign(nelements, "(message_end - in) / (%s)" %(element_type.get_fixed_nw_size())) + else: + raise NotImplementedError("TODO array[] of dynamic element size not done yet") + elif array.is_image_size_length(): + bpp = array.size[1] + width = array.size[2] + rows = array.size[3] + width_v = dest.get_ref(width) + rows_v = dest.get_ref(rows) + # TODO: Handle multiplication overflow + if bpp == 8: + writer.assign(nelements, "%s * %s" % (width_v, rows_v)) + elif bpp == 1: + writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v)) + else: + writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v)) + elif array.is_bytes_length(): + writer.assign(nelements, dest.get_ref(array.size[2])) + else: + raise NotImplementedError("TODO array size type not handled yet") + return nelements + +def write_switch_parser(writer, container, switch, dest, scope): + var = container.lookup_member(switch.variable) + var_type = var.member_type + + if switch.has_attr("fixedsize"): + scope.variable_def("uint8_t *", "in_save") + writer.assign("in_save", "in") + + first = True + for c in switch.cases: + check = c.get_check(dest.get_ref(switch.variable), var_type) + m = c.member + with writer.if_block(check, not first, False) as block: + t = m.member_type + if switch.has_end_attr(): + dest2 = dest.child_at_end(writer, m.member_type) + elif switch.has_attr("anon"): + if t.is_struct() and not m.has_attr("to_ptr"): + dest2 = dest.child_sub(m.name) + else: + dest2 = dest + else: + if t.is_struct(): + dest2 = dest.child_sub(switch.name + "." + m.name) + else: + dest2 = dest.child_sub(switch.name) + dest2.reuse_scope = block + + if m.has_attr("to_ptr"): + write_parse_to_pointer(writer, t, False, dest2, m.name, block) + elif t.is_pointer(): + write_parse_pointer(writer, t, False, dest2, m.name, block) + elif t.is_struct(): + write_container_parser(writer, t, dest2) + elif t.is_primitive(): + if m.has_attr("zero"): + writer.statement("consume_%s(&in)" % (t.primitive_type())) + else: + writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type())) + #TODO validate e.g. flags and enums + elif t.is_array(): + nelements = read_array_len(writer, m.name, t, dest, block, False) + write_array_parser(writer, m, nelements, t, dest2, block) + else: + writer.todo("Can't handle type %s" % m.member_type) + + first = False + + writer.newline() + + if switch.has_attr("fixedsize"): + writer.assign("in", "in_save + %s" % switch.get_fixed_nw_size()) + +def write_parse_ptr_function(writer, target_type): + if target_type.is_array(): + parse_function = "parse_array_%s" % target_type.element_type.primitive_type() + else: + parse_function = "parse_struct_%s" % target_type.c_type() + if writer.is_generated("parser", parse_function): + return parse_function + + writer.set_is_generated("parser", parse_function) + + writer = writer.function_helper() + scope = writer.function(parse_function, "static uint8_t *", "uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, SPICE_GNUC_UNUSED int minor") + scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset") + scope.variable_def("uint8_t *", "end") + + num_pointers = target_type.get_num_pointers() + if num_pointers != 0: + scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") + scope.variable_def("uint32_t", "n_ptr=0") + scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers) + + writer.newline() + if target_type.is_array(): + writer.assign("end", "struct_data") + else: + writer.assign("end", "struct_data + %s" % (target_type.sizeof())) + + dest = RootDemarshallingDestination(None, target_type.c_type(), target_type.sizeof(), "struct_data") + dest.is_helper = True + dest.reuse_scope = scope + if target_type.is_array(): + write_array_parser(writer, None, "this_ptr_info->nelements", target_type, dest, scope) + else: + write_container_parser(writer, target_type, dest) + + if num_pointers != 0: + write_ptr_info_check(writer) + + writer.statement("return end") + + if writer.has_error_check: + writer.newline() + writer.label("error") + writer.statement("return NULL") + + writer.end_block() + + return parse_function + +def write_array_parser(writer, member, nelements, array, dest, scope): + is_byte_size = array.is_bytes_length() + + element_type = array.element_type + if member: + array_start = dest.get_ref(member.name) + at_end = member.has_attr("end") + else: + array_start = "end" + at_end = True + + if element_type == ptypes.uint8 or element_type == ptypes.int8: + writer.statement("memcpy(%s, in, %s)" % (array_start, nelements)) + writer.increment("in", nelements) + if at_end: + writer.increment("end", nelements) + else: + with writer.index() as index: + if member: + array_pos = "%s[%s]" % (array_start, index) + else: + array_pos = "*(%s *)end" % (element_type.c_type()) + + if array.has_attr("ptr_array"): + scope.variable_def("void **", "ptr_array") + scope.variable_def("int", "ptr_array_index") + writer.assign("ptr_array_index", 0) + writer.assign("ptr_array", "(void **)%s" % array_start) + writer.increment("end", "sizeof(void *) * %s" % nelements) + array_start = "end" + array_pos = "*(%s *)end" % (element_type.c_type()) + at_end = True + + with writer.for_loop(index, nelements) as array_scope: + if array.has_attr("ptr_array"): + writer.statement("ptr_array[ptr_array_index++] = end") + if element_type.is_primitive(): + writer.statement("%s = consume_%s(&in)" % (array_pos, element_type.primitive_type())) + if at_end: + writer.increment("end", element_type.sizeof()) + else: + if at_end: + dest2 = dest.child_at_end(writer, element_type) + else: + dest2 = RootDemarshallingDestination(dest, element_type.c_type(), element_type.c_type(), array_pos) + dest2.reuse_scope = array_scope + write_container_parser(writer, element_type, dest2) + if array.has_attr("ptr_array"): + writer.comment("Align ptr_array element to 4 bytes").newline() + writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") + +def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_name, scope): + writer.assign("ptr_info[n_ptr].offset", offset) + writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type)) + if at_end: + writer.assign("ptr_info[n_ptr].dest", "(void **)end") + writer.increment("end", "sizeof(void *)") + else: + writer.assign("ptr_info[n_ptr].dest", "(void **)&%s" % dest.get_ref(member_name)) + if target_type.is_array(): + nelements = read_array_len(writer, member_name, target_type, dest, scope, True) + writer.assign("ptr_info[n_ptr].nelements", nelements) + + writer.statement("n_ptr++") + +def write_parse_pointer(writer, t, at_end, dest, member_name, scope): + write_parse_pointer_core(writer, t.target_type, "consume_%s(&in)" % t.primitive_type(), + at_end, dest, member_name, scope) + +def write_parse_to_pointer(writer, t, at_end, dest, member_name, scope): + write_parse_pointer_core(writer, t, "in - start", + at_end, dest, member_name, scope) + writer.increment("in", "%s__saved_size" % member_name) + +def write_member_parser(writer, container, member, dest, scope): + if member.has_attr("virtual"): + writer.assign(dest.get_ref(member.name), member.attributes["virtual"][0]) + return + + if member.is_switch(): + write_switch_parser(writer, container, member, dest, scope) + return + + t = member.member_type + + if member.has_attr("to_ptr"): + write_parse_to_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) + elif t.is_pointer(): + if member.has_attr("chunk"): + assert(t.target_type.is_array()) + nelements = read_array_len(writer, member.name, t.target_type, dest, scope, True) + writer.comment("Reuse data from network message as chunk").newline() + scope.variable_def("SpiceChunks *", "chunks") + writer.assign("chunks", "(SpiceChunks *)end") + writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)") + writer.assign(dest.get_ref(member.name), "chunks") + writer.assign("chunks->data_size", nelements) + writer.assign("chunks->flags", 0) + writer.assign("chunks->num_chunks", 1) + writer.assign("chunks->chunk[0].len", nelements) + writer.assign("chunks->chunk[0].data", "message_start + consume_%s(&in)" % t.primitive_type()) + elif member.has_attr("nocopy"): + writer.comment("Reuse data from network message").newline() + writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_%s(&in))" % t.primitive_type()) + else: + write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope) + elif t.is_primitive(): + if member.has_attr("zero"): + writer.statement("consume_%s(&in)" % t.primitive_type()) + elif member.has_end_attr(): + writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type())) + writer.increment("end", t.sizeof()) + else: + if member.has_attr("bytes_count"): + dest_var = dest.get_ref(member.attributes["bytes_count"][0]) + else: + dest_var = dest.get_ref(member.name) + writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type())) + #TODO validate e.g. flags and enums + elif t.is_array(): + nelements = read_array_len(writer, member.name, t, dest, scope, False) + if member.has_attr("chunk") and t.element_type.is_fixed_nw_size() and t.element_type.get_fixed_nw_size() == 1: + writer.comment("use array as chunk").newline() + + scope.variable_def("SpiceChunks *", "chunks") + writer.assign("chunks", "(SpiceChunks *)end") + writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)") + writer.assign(dest.get_ref(member.name), "chunks") + writer.assign("chunks->data_size", nelements) + writer.assign("chunks->flags", 0) + writer.assign("chunks->num_chunks", 1) + writer.assign("chunks->chunk[0].len", nelements) + writer.assign("chunks->chunk[0].data", "in") + writer.increment("in", "%s" % (nelements)) + elif member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size(): + writer.comment("use array as pointer").newline() + writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type()) + len_var = member.attributes["as_ptr"] + if len(len_var) > 0: + writer.assign(dest.get_ref(len_var[0]), nelements) + el_size = t.element_type.get_fixed_nw_size() + if el_size != 1: + writer.increment("in", "%s * %s" % (nelements, el_size)) + else: + writer.increment("in", "%s" % (nelements)) + else: + write_array_parser(writer, member, nelements, t, dest, scope) + elif t.is_struct(): + if member.has_end_attr(): + dest2 = dest.child_at_end(writer, t) + else: + dest2 = dest.child_sub(member.name) + writer.comment(member.name) + write_container_parser(writer, t, dest2) + else: + raise NotImplementedError("TODO can't handle parsing of %s" % t) + +def write_container_parser(writer, container, dest): + with dest.declare(writer) as scope: + for m in container.members: + if m.has_minor_attr(): + writer.begin_block("if (minor >= %s)" % m.get_minor_attr()) + write_member_parser(writer, container, m, dest, scope) + if m.has_minor_attr(): + # We need to zero out the fixed part of all optional fields + if not m.member_type.is_array(): + writer.end_block(newline=False) + writer.begin_block(" else") + # TODO: This is not right for fields that don't exist in the struct + if m.has_attr("zero"): + pass + elif m.member_type.is_primitive(): + writer.assign(dest.get_ref(m.name), "0") + elif m.is_fixed_sizeof(): + writer.statement("memset ((char *)&%s, 0, %s)" % (dest.get_ref(m.name), m.sizeof())) + else: + raise NotImplementedError("TODO Clear optional dynamic fields") + writer.end_block() + +def write_ptr_info_check(writer): + writer.newline() + with writer.index() as index: + with writer.for_loop(index, "n_ptr") as scope: + offset = "ptr_info[%s].offset" % index + function = "ptr_info[%s].parse" % index + dest = "ptr_info[%s].dest" % index + with writer.if_block("%s == 0" % offset, newline=False): + writer.assign("*%s" % dest, "NULL") + with writer.block(" else"): + writer.comment("Align to 32 bit").newline() + writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)") + writer.assign("*%s" % dest, "(void *)end") + writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index)) + writer.error_check("end == NULL") + writer.newline() + +def write_nofree(writer): + if writer.is_generated("helper", "nofree"): + return + writer = writer.function_helper() + scope = writer.function("nofree", "static void", "SPICE_GNUC_UNUSED uint8_t *data") + writer.end_block() + +def write_msg_parser(writer, message): + msg_name = message.c_name() + function_name = "parse_%s" % msg_name + if writer.is_generated("demarshaller", function_name): + return function_name + writer.set_is_generated("demarshaller", function_name) + + msg_type = message.c_type() + msg_sizeof = message.sizeof() + + want_mem_size = (len(message.members) != 1 or message.members[0].is_fixed_nw_size() + or not message.members[0].is_array()) + + writer.newline() + if message.has_attr("ifdef"): + writer.ifdef(message.attributes["ifdef"][0]) + parent_scope = writer.function(function_name, + "uint8_t *", + "uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message", True) + parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos") + parent_scope.variable_def("uint8_t *", "start = message_start") + parent_scope.variable_def("uint8_t *", "data = NULL") + parent_scope.variable_def("size_t", "nw_size") + if want_mem_size: + parent_scope.variable_def("size_t", "mem_size") + if not message.has_attr("nocopy"): + parent_scope.variable_def("uint8_t *", "in", "end") + num_pointers = message.get_num_pointers() + if num_pointers != 0: + parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size") + parent_scope.variable_def("uint32_t", "n_ptr=0") + parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers) + writer.newline() + + write_parser_helpers(writer) + + write_validate_container(writer, None, message, "start", parent_scope, True, + want_mem_size=want_mem_size, want_extra_size=False) + + writer.newline() + + writer.comment("Check if message fits in reported side").newline() + with writer.block("if (start + nw_size > message_end)"): + writer.statement("return NULL") + + writer.newline().comment("Validated extents and calculated size").newline() + + if message.has_attr("nocopy"): + write_nofree(writer) + writer.assign("data", "message_start") + writer.assign("*size", "message_end - message_start") + writer.assign("*free_message", "nofree") + else: + writer.assign("data", "(uint8_t *)malloc(mem_size)") + writer.error_check("data == NULL") + writer.assign("end", "data + %s" % (msg_sizeof)) + writer.assign("in", "start").newline() + + # avoid defined and assigned but not used warnings of gcc 4.6.0+ + if message.is_extra_size() or not message.is_fixed_nw_size() or message.get_fixed_nw_size() > 0: + dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data") + dest.reuse_scope = parent_scope + write_container_parser(writer, message, dest) + + writer.newline() + writer.statement("assert(in <= message_end)") + + if num_pointers != 0: + write_ptr_info_check(writer) + + writer.statement("assert(end <= data + mem_size)") + + writer.newline() + writer.assign("*size", "end - data") + writer.assign("*free_message", "(message_destructor_t) free") + + writer.statement("return data") + writer.newline() + if writer.has_error_check: + writer.label("error") + with writer.block("if (data != NULL)"): + writer.statement("free(data)") + writer.statement("return NULL") + writer.end_block() + + if message.has_attr("ifdef"): + writer.endif(message.attributes["ifdef"][0]) + + return function_name + +def write_channel_parser(writer, channel, server): + writer.newline() + ids = {} + min_id = 1000000 + if server: + messages = channel.server_messages + else: + messages = channel.client_messages + for m in messages: + ids[m.value] = m + + ranges = [] + ids2 = ids.copy() + while len(ids2) > 0: + end = start = min(ids2.keys()) + while end in ids2: + del ids2[end] + end = end + 1 + + ranges.append( (start, end) ) + + if server: + function_name = "parse_%s_msg" % channel.name + else: + function_name = "parse_%s_msgc" % channel.name + writer.newline() + if channel.has_attr("ifdef"): + writer.ifdef(channel.attributes["ifdef"][0]) + scope = writer.function(function_name, + "static uint8_t *", + "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message") + + helpers = writer.function_helper() + + d = 0 + for r in ranges: + d = d + 1 + writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0])) + writer.begin_block() + for i in range(r[0], r[1]): + func = write_msg_parser(helpers, ids[i].message_type) + writer.write(func) + if i != r[1] -1: + writer.write(",") + writer.newline() + + writer.end_block(semicolon = True) + + d = 0 + for r in ranges: + d = d + 1 + with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False): + writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out, free_message)" % (d, r[0])) + writer.newline() + + writer.statement("return NULL") + writer.end_block() + if channel.has_attr("ifdef"): + writer.endif(channel.attributes["ifdef"][0]) + + return function_name + +def write_get_channel_parser(writer, channel_parsers, max_channel, is_server): + writer.newline() + if is_server: + function_name = "spice_get_server_channel_parser" + writer.public_prefix + else: + function_name = "spice_get_client_channel_parser" + writer.public_prefix + + scope = writer.function(function_name, + "spice_parse_channel_func_t", + "uint32_t channel, unsigned int *max_message_type") + + writer.write("static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[%d] = " % (max_channel+1)) + writer.begin_block() + channel = None + for i in range(0, max_channel + 1): + if i in channel_parsers: + channel = channel_parsers[i][0] + if channel.has_attr("ifdef"): + writer.ifdef(channel.attributes["ifdef"][0]) + writer.write("{ ") + writer.write(channel_parsers[i][1]) + writer.write(", ") + + max_msg = 0 + if is_server: + messages = channel.server_messages + else: + messages = channel.client_messages + for m in messages: + max_msg = max(max_msg, m.value) + writer.write(max_msg) + writer.write("}") + else: + writer.write("{ NULL, 0 }") + + if i != max_channel: + writer.write(",") + writer.newline() + if channel and channel.has_attr("ifdef"): + writer.ifdef_else(channel.attributes["ifdef"][0]) + writer.write("{ NULL, 0 }") + if i != max_channel: + writer.write(",") + writer.newline() + writer.endif(channel.attributes["ifdef"][0]) + writer.end_block(semicolon = True) + + with writer.if_block("channel < %d" % (max_channel + 1)): + with writer.if_block("max_message_type != NULL"): + writer.assign("*max_message_type", "channels[channel].max_messages") + writer.statement("return channels[channel].func") + + writer.statement("return NULL") + writer.end_block() + + +def write_full_protocol_parser(writer, is_server): + writer.newline() + if is_server: + function_name = "spice_parse_msg" + else: + function_name = "spice_parse_reply" + scope = writer.function(function_name + writer.public_prefix, + "uint8_t *", + "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message") + scope.variable_def("spice_parse_channel_func_t", "func" ) + + if is_server: + writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix) + else: + writer.assign("func", "spice_get_client_channel_parser%s(channel, NULL)" % writer.public_prefix) + + with writer.if_block("func != NULL"): + writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)") + + writer.statement("return NULL") + writer.end_block() + +def write_protocol_parser(writer, proto, is_server): + max_channel = 0 + parsers = {} + + for channel in proto.channels: + max_channel = max(max_channel, channel.value) + + parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server)) + + write_get_channel_parser(writer, parsers, max_channel, is_server) + write_full_protocol_parser(writer, is_server) + +def write_includes(writer): + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln('#include ') + writer.newline() + writer.writeln("#ifdef _MSC_VER") + writer.writeln("#pragma warning(disable:4101)") + writer.writeln("#endif") diff --git a/spice-common/python_modules/marshal.py b/spice-common/python_modules/marshal.py new file mode 100644 index 0000000..1d38d3d --- /dev/null +++ b/spice-common/python_modules/marshal.py @@ -0,0 +1,420 @@ + +from . import ptypes +from . import codegen + +def write_includes(writer): + writer.header.writeln("#include ") + writer.header.writeln('#include "common/marshaller.h"') + writer.header.newline() + writer.header.writeln("#ifndef _GENERATED_HEADERS_H") + writer.header.writeln("#define _GENERATED_HEADERS_H") + + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln("#include ") + writer.writeln('#include "common/marshaller.h"') + writer.newline() + writer.writeln("#ifdef _MSC_VER") + writer.writeln("#pragma warning(disable:4101)") + writer.writeln("#pragma warning(disable:4018)") + writer.writeln("#endif") + writer.newline() + +class MarshallingSource: + def __init__(self): + pass + + def child_at_end(self, t): + return RootMarshallingSource(self, t.c_type(), t.sizeof()) + + def child_sub(self, containee): + return SubMarshallingSource(self, containee) + + def declare(self, writer): + return writer.optional_block(self.reuse_scope) + + def is_toplevel(self): + return self.parent_src == None and not self.is_helper + +class RootMarshallingSource(MarshallingSource): + def __init__(self, parent_src, c_type, sizeof, pointer = None): + self.is_helper = False + self.reuse_scope = None + self.parent_src = parent_src + if parent_src: + self.base_var = codegen.increment_identifier(parent_src.base_var) + else: + self.base_var = "src" + self.c_type = c_type + self.sizeof = sizeof + self.pointer = pointer + assert pointer != None + + def get_self_ref(self): + return self.base_var + + def get_ref(self, member): + return self.base_var + "->" + member + + def declare(self, writer): + if self.reuse_scope: + scope = self.reuse_scope + else: + writer.begin_block() + scope = writer.get_subwriter() + + scope.variable_def(self.c_type + " *", self.base_var) + if not self.reuse_scope: + scope.newline() + + writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer)) + writer.newline() + + if self.reuse_scope: + return writer.no_block(self.reuse_scope) + else: + return writer.partial_block(scope) + +class SubMarshallingSource(MarshallingSource): + def __init__(self, parent_src, containee): + self.reuse_scope = None + self.parent_src = parent_src + self.base_var = parent_src.base_var + self.containee = containee + self.name = containee.name + self.is_helper = False + + def get_self_ref(self): + if self.containee.has_attr("to_ptr"): + return "%s" % self.parent_src.get_ref(self.name) + else: + return "&%s" % self.parent_src.get_ref(self.name) + + def get_ref(self, member): + if self.containee.has_attr("to_ptr"): + return self.parent_src.get_ref(self.name) + "->" + member + else: + return self.parent_src.get_ref(self.name) + "." + member + +def write_marshal_ptr_function(writer, target_type, is_helper=True): + if target_type.is_array(): + marshal_function = "spice_marshall_array_%s" % target_type.element_type.primitive_type() + else: + marshal_function = "spice_marshall_%s" % target_type.name + if writer.is_generated("marshaller", marshal_function): + return marshal_function + + writer.set_is_generated("marshaller", marshal_function) + + names = target_type.get_pointer_names(False) + names_args = "" + if len(names) > 0: + n = [", SpiceMarshaller **%s_out" % name for name in names] + names_args = "".join(n) + + header = writer.header + if is_helper: + writer = writer.function_helper() + writer.header = header + writer.out_prefix = "" + if target_type.is_array(): + scope = writer.function(marshal_function, "SPICE_GNUC_UNUSED static void", "SpiceMarshaller *m, %s_t *ptr, unsigned count" % target_type.element_type.primitive_type() + names_args) + else: + scope = writer.function(marshal_function, "void", "SpiceMarshaller *m, %s *ptr" % target_type.c_type() + names_args) + header.writeln("void " + marshal_function + "(SpiceMarshaller *m, %s *msg" % target_type.c_type() + names_args + ");") + scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2") + + for n in names: + writer.assign("*%s_out" % n, "NULL") + + writer.newline() + + if target_type.is_struct(): + src = RootMarshallingSource(None, target_type.c_type(), target_type.sizeof(), "ptr") + src.reuse_scope = scope + write_container_marshaller(writer, target_type, src) + elif target_type.is_array() and target_type.element_type.is_primitive(): + with writer.index() as index: + with writer.for_loop(index, "count") as array_scope: + writer.statement("spice_marshaller_add_%s(m, *ptr++)" % (target_type.element_type.primitive_type())) + else: + writer.todo("Unsuppored pointer marshaller type") + + writer.end_block() + + return marshal_function + +def get_array_size(array, container_src): + if array.is_constant_length(): + return array.size + elif array.is_identifier_length(): + return container_src.get_ref(array.size) + elif array.is_remaining_length(): + raise NotImplementedError("remaining size array sizes marshalling not supported") + elif array.is_image_size_length(): + bpp = array.size[1] + width = array.size[2] + rows = array.size[3] + width_v = container_src.get_ref(width) + rows_v = container_src.get_ref(rows) + # TODO: Handle multiplication overflow + if bpp == 8: + return "(unsigned) (%s * %s)" % (width_v, rows_v) + elif bpp == 1: + return "(unsigned) (((%s + 7) / 8 ) * %s)" % (width_v, rows_v) + else: + return "(unsigned) (((%s * %s + 7) / 8 ) * %s)" % (bpp, width_v, rows_v) + elif array.is_bytes_length(): + return container_src.get_ref(array.size[2]) + else: + raise NotImplementedError("TODO array size type not handled yet: %s" % array) + +def write_array_marshaller(writer, member, array, container_src, scope): + element_type = array.element_type + + if array.is_remaining_length(): + writer.comment("Remaining data must be appended manually").newline() + return + + nelements = get_array_size(array, container_src) + is_byte_size = array.is_bytes_length() + + element = "%s__element" % member.name + + if not scope.variable_defined(element): + if array.has_attr("ptr_array"): + stars = " **" + else: + stars = " *" + scope.variable_def(element_type.c_type() + stars, element) + element_array = element + if array.has_attr("ptr_array"): + element = "*" + element + + writer.assign(element_array, container_src.get_ref(member.name)) + + if is_byte_size: + size_start_var = "%s__size_start" % member.name + scope.variable_def("size_t", size_start_var) + writer.assign(size_start_var, "spice_marshaller_get_size(m)") + + with writer.index() as index: + with writer.for_loop(index, nelements) as array_scope: + if element_type.is_primitive(): + writer.statement("spice_marshaller_add_%s(m, *%s)" % (element_type.primitive_type(), element)) + elif element_type.is_struct(): + src2 = RootMarshallingSource(container_src, element_type.c_type(), element_type.sizeof(), element) + src2.reuse_scope = array_scope + write_container_marshaller(writer, element_type, src2) + else: + writer.todo("array element unhandled type").newline() + + writer.statement("%s++" % element_array) + + if is_byte_size: + size_var = member.container.lookup_member(array.size[1]) + size_var_type = size_var.member_type + var = "%s__ref" % array.size[1] + writer.statement("spice_marshaller_set_%s(m, %s, spice_marshaller_get_size(m) - %s)" % (size_var_type.primitive_type(), var, size_start_var)) + +def write_pointer_marshaller(writer, member, src): + t = member.member_type + ptr_func = write_marshal_ptr_function(writer, t.target_type) + submarshaller = "spice_marshaller_get_ptr_submarshaller(m, %d)" % (1 if member.get_fixed_nw_size() == 8 else 0) + if member.has_attr("marshall"): + rest_args = "" + if t.target_type.is_array(): + rest_args = ", %s" % get_array_size(t.target_type, src) + writer.assign("m2", submarshaller) + if t.has_attr("nonnull"): + writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args)) + else: + with writer.if_block("%s != NULL" % src.get_ref(member.name)) as block: + writer.statement("%s(m2, %s%s)" % (ptr_func, src.get_ref(member.name), rest_args)) + else: + writer.assign("*%s_out" % (writer.out_prefix + member.name), submarshaller) + +def write_switch_marshaller(writer, container, switch, src, scope): + var = container.lookup_member(switch.variable) + var_type = var.member_type + + saved_out_prefix = writer.out_prefix + first = True + for c in switch.cases: + check = c.get_check(src.get_ref(switch.variable), var_type) + m = c.member + writer.out_prefix = saved_out_prefix + if m.has_attr("outvar"): + writer.out_prefix = "%s_%s" % (m.attributes["outvar"][0], writer.out_prefix) + with writer.if_block(check, not first, False) as block: + t = m.member_type + if switch.has_attr("anon"): + if t.is_struct(): + src2 = src.child_sub(m) + else: + src2 = src + else: + if t.is_struct(): + src2 = src.child_sub(switch).child_sub(m) + else: + src2 = src.child_sub(switch) + src2.reuse_scope = block + + if t.is_struct(): + write_container_marshaller(writer, t, src2) + elif t.is_pointer(): + write_pointer_marshaller(writer, m, src2) + elif t.is_primitive(): + if m.has_attr("zero"): + writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type())) + else: + writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src2.get_ref(m.name))) + #TODO validate e.g. flags and enums + elif t.is_array(): + write_array_marshaller(writer, m, t, src2, scope) + else: + writer.todo("Can't handle type %s" % m.member_type) + + if switch.has_attr("fixedsize"): + remaining = switch.get_fixed_nw_size() - t.get_fixed_nw_size() + if remaining != 0: + writer.statement("spice_marshaller_reserve_space(m, %s)" % remaining) + + first = False + if switch.has_attr("fixedsize"): + with writer.block(" else"): + writer.statement("spice_marshaller_reserve_space(m, %s)" % switch.get_fixed_nw_size()) + + writer.newline() + +def write_member_marshaller(writer, container, member, src, scope): + if member.has_attr("outvar"): + writer.out_prefix = "%s_%s" % (member.attributes["outvar"][0], writer.out_prefix) + if member.has_attr("virtual"): + writer.comment("Don't marshall @virtual %s" % member.name).newline() + return + if member.has_attr("nomarshal"): + writer.comment("Don't marshall @nomarshal %s" % member.name).newline() + return + if member.is_switch(): + write_switch_marshaller(writer, container, member, src, scope) + return + + t = member.member_type + + if t.is_pointer(): + write_pointer_marshaller(writer, member, src) + elif t.is_primitive(): + if member.has_attr("zero"): + writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type())) + if member.has_attr("bytes_count"): + var = "%s__ref" % member.name + scope.variable_def("void *", var) + writer.statement("%s = spice_marshaller_add_%s(m, %s)" % (var, t.primitive_type(), 0)) + + else: + writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src.get_ref(member.name))) + elif t.is_array(): + write_array_marshaller(writer, member, t, src, scope) + elif t.is_struct(): + src2 = src.child_sub(member) + writer.comment(member.name) + write_container_marshaller(writer, t, src2) + else: + raise NotImplementedError("TODO can't handle parsing of %s" % t) + +def write_container_marshaller(writer, container, src): + saved_out_prefix = writer.out_prefix + with src.declare(writer) as scope: + for m in container.members: + writer.out_prefix = saved_out_prefix + write_member_marshaller(writer, container, m, src, scope) + +def write_message_marshaller(writer, message, is_server, private): + if message.has_attr("ifdef"): + writer.ifdef(message.attributes["ifdef"][0]) + writer.out_prefix = "" + function_name = "spice_marshall_" + message.c_name() + if writer.is_generated("marshaller", function_name): + return function_name + writer.set_is_generated("marshaller", function_name) + + names = message.get_pointer_names(False) + names_args = "" + if len(names) > 0: + n = [", SpiceMarshaller **%s_out" % name for name in names] + names_args = "".join(n) + + if not private: + writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");") + + scope = writer.function(function_name, + "static void" if private else "void", + "SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED %s *msg" % message.c_type() + names_args) + scope.variable_def("SPICE_GNUC_UNUSED SpiceMarshaller *", "m2") + + for n in names: + writer.assign("*%s_out" % n, "NULL") + + # fix warnings about unused variables by not creating body if no members to parse + if any(x.is_fixed_nw_size() for x in message.members): + src = RootMarshallingSource(None, message.c_type(), message.sizeof(), "msg") + src.reuse_scope = scope + + write_container_marshaller(writer, message, src) + + writer.end_block() + if message.has_attr("ifdef"): + writer.endif(message.attributes["ifdef"][0]) + writer.newline() + return function_name + +def write_protocol_marshaller(writer, proto, is_server, private_marshallers): + functions = {} + for c in proto.channels: + channel = c.channel_type + if channel.has_attr("ifdef"): + writer.ifdef(channel.attributes["ifdef"][0]) + writer.header.ifdef(channel.attributes["ifdef"][0]) + if is_server: + messages = channel.client_messages + else: + messages = channel.server_messages + for m in messages: + message = m.message_type + f = write_message_marshaller(writer, message, is_server, private_marshallers) + if channel.has_attr("ifdef") and f not in functions: + functions[f] = channel.attributes["ifdef"][0] + elif message.has_attr("ifdef") and f not in functions: + functions[f] = message.attributes["ifdef"][0] + else: + functions[f] = True + if channel.has_attr("ifdef"): + writer.endif(channel.attributes["ifdef"][0]) + writer.header.endif(channel.attributes["ifdef"][0]) + + if private_marshallers: + scope = writer.function("spice_message_marshallers_get" + writer.public_prefix, + "SpiceMessageMarshallers *", + "void") + writer.writeln("static SpiceMessageMarshallers marshallers = {NULL};").newline() + for f in sorted(functions.keys()): + member = f[len("spice_marshall_"):] + if not member.startswith("msg"): + member = "msg_" + member + if functions[f] != True: + writer.ifdef(functions[f]) + writer.assign("marshallers.%s" % member, f) + if functions[f] != True: + writer.endif(functions[f]) + + writer.newline() + writer.statement("return &marshallers") + writer.end_block() + writer.newline() + +def write_trailer(writer): + writer.header.writeln("#endif") diff --git a/spice-common/python_modules/ptypes.py b/spice-common/python_modules/ptypes.py new file mode 100644 index 0000000..753d363 --- /dev/null +++ b/spice-common/python_modules/ptypes.py @@ -0,0 +1,1138 @@ +from . import codegen +import types + +_types_by_name = {} +_types = [] + +default_pointer_size = 4 + +def type_exists(name): + return name in _types_by_name + +def lookup_type(name): + return _types_by_name[name] + +def get_named_types(): + return _types + +class FixedSize: + def __init__(self, val = 0, minor = 0): + if isinstance(val, FixedSize): + self.vals = val.vals + else: + self.vals = [0] * (minor + 1) + self.vals[minor] = val + + def __add__(self, other): + if isinstance(other, int): + other = FixedSize(other) + + new = FixedSize() + l = max(len(self.vals), len(other.vals)) + shared = min(len(self.vals), len(other.vals)) + + new.vals = [0] * l + + for i in range(shared): + new.vals[i] = self.vals[i] + other.vals[i] + + for i in range(shared,len(self.vals)): + new.vals[i] = self.vals[i] + + for i in range(shared,len(other.vals)): + new.vals[i] = new.vals[i] + other.vals[i] + + return new + + def __radd__(self, other): + return self.__add__(other) + + def __str__(self): + s = "%d" % (self.vals[0]) + + for i in range(1,len(self.vals)): + if self.vals[i] > 0: + s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i]) + return s + +# Some attribute are propagated from member to the type as they really +# are part of the type definition, rather than the member. This applies +# only to attributes that affect pointer or array attributes, as these +# are member local types, unlike e.g. a Struct that may be used by +# other members +propagated_attributes=["ptr_array", "nonnull", "chunk"] + +valid_attributes=set([ + # embedded/appended at the end of the structure + 'end', + # the C structure contains a pointer to data + # for instance we want to write an array to an allocated array + 'to_ptr', + # write output to this C structure + 'ctype', + # prefix for flags/values enumerations + 'prefix', + # used in demarshaller to use directly data from message without a copy + 'nocopy', + # store member array in a pointer + # similar to to_ptr but has an additional argument which is the name of a C + # field which will store the array length + 'as_ptr', + # do not generate marshall code + # used for last members to be able to marshall them manually + 'nomarshal', + # ??? not used by python code + 'zero_terminated', + 'marshall', + # this pointer member cannot be null + 'nonnull', + # this flag member contains only a single flag + 'unique_flag', + 'ptr_array', + 'outvar', + # C structure has an anonymous member (used in switch) + 'anon', + 'chunk', + # this channel is contained in an #ifdef section + # the argument specifies the preprocessor define to check + 'ifdef', + # write this member as zero on network + 'zero', + # specify minor version required for these members + 'minor', + # this member contains the byte count for an array. + # the argument is the member name for item count (not bytes) + 'bytes_count', + # this attribute does not exist on the network, fill just structure with the value + 'virtual', + # for a switch this indicates that on network + # it will occupy always the same size (maximum size required for all members) + 'fixedsize', +]) + +attributes_with_arguments=set([ + 'ctype', + 'prefix', + 'as_ptr', + 'outvar', + 'ifdef', + 'minor', + 'bytes_count', + 'virtual', +]) + +def fix_attributes(attribute_list): + attrs = {} + for attr in attribute_list: + name = attr[0][1:] + lst = attr[1:] + if not name in valid_attributes: + raise Exception("Attribute %s not recognized" % name) + if not name in attributes_with_arguments: + if len(lst) > 0: + raise Exception("Attribute %s specified with options" % name) + elif len(lst) > 1: + raise Exception("Attribute %s has more than 1 argument" % name) + attrs[name] = lst + return attrs + +class Type: + def __init__(self): + self.attributes = {} + self.registred = False + self.name = None + + def has_name(self): + return self.name != None + + def get_type(self, recursive=False): + return self + + def is_primitive(self): + return False + + def is_fixed_sizeof(self): + return True + + def is_extra_size(self): + return False + + def contains_extra_size(self): + return False + + def is_fixed_nw_size(self): + return True + + def is_array(self): + return isinstance(self, ArrayType) + + def contains_member(self, member): + return False + + def is_struct(self): + return isinstance(self, StructType) + + def is_pointer(self): + return isinstance(self, PointerType) + + def get_num_pointers(self): + return 0 + + def get_pointer_names(self, marshalled): + return [] + + def sizeof(self): + return "sizeof(%s)" % (self.c_type()) + + def __repr__(self): + return self.__str__() + + def __str__(self): + if self.name != None: + return self.name + return "anonymous type" + + def resolve(self): + return self + + def register(self): + if self.registred or self.name == None: + return + self.registred = True + if self.name in _types_by_name: + raise Exception("Type %s already defined" % self.name) + _types.append(self) + _types_by_name[self.name] = self + + def has_attr(self, name): + if not name in valid_attributes: + raise Exception('attribute %s not expected' % name) + return name in self.attributes + +class TypeRef(Type): + def __init__(self, name): + Type.__init__(self) + self.name = name + + def __str__(self): + return "ref to %s" % (self.name) + + def resolve(self): + if self.name not in _types_by_name: + raise Exception("Unknown type %s" % self.name) + return _types_by_name[self.name] + + def register(self): + assert True, "Can't register TypeRef!" + + +class IntegerType(Type): + def __init__(self, bits, signed): + Type.__init__(self) + self.bits = bits + self.signed = signed + + if signed: + self.name = "int%d" % bits + else: + self.name = "uint%d" % bits + + def primitive_type(self): + return self.name + + def c_type(self): + return self.name + "_t" + + def get_fixed_nw_size(self): + return self.bits // 8 + + def is_primitive(self): + return True + +class TypeAlias(Type): + def __init__(self, name, the_type, attribute_list): + Type.__init__(self) + self.name = name + self.the_type = the_type + self.attributes = fix_attributes(attribute_list) + + def get_type(self, recursive=False): + if recursive: + return self.the_type.get_type(True) + else: + return self.the_type + + def primitive_type(self): + return self.the_type.primitive_type() + + def resolve(self): + self.the_type = self.the_type.resolve() + return self + + def __str__(self): + return "alias %s" % self.name + + def is_primitive(self): + return self.the_type.is_primitive() + + def is_fixed_sizeof(self): + return self.the_type.is_fixed_sizeof() + + def is_fixed_nw_size(self): + return self.the_type.is_fixed_nw_size() + + def get_fixed_nw_size(self): + return self.the_type.get_fixed_nw_size() + + def get_num_pointers(self): + return self.the_type.get_num_pointers() + + def get_pointer_names(self, marshalled): + return self.the_type.get_pointer_names(marshalled) + + def c_type(self): + if self.has_attr("ctype"): + return self.attributes["ctype"][0] + return self.name + +class EnumBaseType(Type): + def is_enum(self): + return isinstance(self, EnumType) + + def primitive_type(self): + return "uint%d" % (self.bits) + + def c_type(self): + return "uint%d_t" % (self.bits) + + def c_name(self): + return codegen.prefix_camel(self.name) + + def c_enumname(self, value): + return self.c_enumname_by_name(self.names[value]) + + def c_enumname_by_name(self, name): + if self.has_attr("prefix"): + return self.attributes["prefix"][0] + name + return codegen.prefix_underscore_upper(self.name.upper(), name) + + def is_primitive(self): + return True + + def get_fixed_nw_size(self): + return self.bits // 8 + + # generates a value-name table suitable for use with the wireshark protocol + # dissector + def c_describe(self, writer): + writer.write("static const value_string %s_vs[] = " % codegen.prefix_underscore_lower(self.name)) + writer.begin_block() + values = list(self.names.keys()) + values.sort() + for i in values: + writer.write("{ ") + writer.write(self.c_enumname(i)) + writer.write(", \"%s\" }," % self.names[i]) + writer.newline() + writer.write("{ 0, NULL }") + writer.end_block(semicolon=True) + writer.newline() + + +class EnumType(EnumBaseType): + def __init__(self, bits, name, enums, attribute_list): + Type.__init__(self) + self.bits = bits + self.name = name + + last = -1 + names = {} + values = {} + for v in enums: + name = v[0] + if len(v) > 1: + value = v[1] + else: + value = last + 1 + last = value + + assert value not in names + names[value] = name + values[name] = value + + self.names = names + self.values = values + + self.attributes = fix_attributes(attribute_list) + + def __str__(self): + return "enum %s" % self.name + + def c_define(self, writer): + writer.write("typedef enum ") + writer.write(self.c_name()) + writer.begin_block() + values = list(self.names.keys()) + values.sort() + current_default = 0 + for i in values: + writer.write(self.c_enumname(i)) + if i != current_default: + writer.write(" = %d" % (i)) + writer.write(",") + writer.newline() + current_default = i + 1 + writer.newline() + writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END")) + writer.newline() + writer.end_block(newline=False) + writer.write(" ") + writer.write(self.c_name()) + writer.write(";") + writer.newline() + writer.newline() + +class FlagsType(EnumBaseType): + def __init__(self, bits, name, flags, attribute_list): + Type.__init__(self) + self.bits = bits + self.name = name + + last = -1 + names = {} + values = {} + for v in flags: + name = v[0] + if len(v) > 1: + value = v[1] + else: + value = last + 1 + last = value + + assert value not in names + names[value] = name + values[name] = value + + self.names = names + self.values = values + + self.attributes = fix_attributes(attribute_list) + + def __str__(self): + return "flags %s" % self.name + + def c_define(self, writer): + writer.write("typedef enum ") + writer.write(self.c_name()) + writer.begin_block() + values = list(self.names.keys()) + values.sort() + mask = 0 + for i in values: + writer.write(self.c_enumname(i)) + mask = mask | (1< 0 + + def is_image_size_length(self): + if isinstance(self.size, int) or isinstance(self.size, str): + return False + return self.size[0] == "image_size" + + def is_bytes_length(self): + if isinstance(self.size, int) or isinstance(self.size, str): + return False + return self.size[0] == "bytes" + + def is_cstring_length(self): + if isinstance(self.size, int) or isinstance(self.size, str): + return False + return self.size[0] == "cstring" + + def is_fixed_sizeof(self): + return self.is_constant_length() and self.element_type.is_fixed_sizeof() + + def is_fixed_nw_size(self): + return self.is_constant_length() and self.element_type.is_fixed_nw_size() + + def get_fixed_nw_size(self): + if not self.is_fixed_nw_size(): + raise Exception("Not a fixed size type") + + return self.element_type.get_fixed_nw_size() * self.size + + def get_num_pointers(self): + element_count = self.element_type.get_num_pointers() + if element_count == 0: + return 0 + if self.is_constant_length(self): + return element_count * self.size + raise Exception("Pointers in dynamic arrays not supported") + + def get_pointer_names(self, marshalled): + element_count = self.element_type.get_num_pointers() + if element_count == 0: + return [] + raise Exception("Pointer names in arrays not supported") + + def is_extra_size(self): + return self.has_attr("ptr_array") + + def contains_extra_size(self): + return self.element_type.contains_extra_size() or self.has_attr("chunk") + + def sizeof(self): + return "%s * %s" % (self.element_type.sizeof(), self.size) + + def c_type(self): + return self.element_type.c_type() + +class PointerType(Type): + def __init__(self, target_type): + Type.__init__(self) + self.name = None + self.target_type = target_type + self.pointer_size = default_pointer_size + + def __str__(self): + return "%s*" % (str(self.target_type)) + + def resolve(self): + self.target_type = self.target_type.resolve() + return self + + def set_ptr_size(self, new_size): + self.pointer_size = new_size + + def is_fixed_nw_size(self): + return True + + def is_primitive(self): + return True + + def primitive_type(self): + if self.pointer_size == 4: + return "uint32" + else: + return "uint64" + + def get_fixed_nw_size(self): + return self.pointer_size + + def c_type(self): + if self.pointer_size == 4: + return "uint32_t" + else: + return "uint64_t" + + def contains_extra_size(self): + return True + + def get_num_pointers(self): + return 1 + +class Containee: + def __init__(self): + self.attributes = {} + + def is_switch(self): + return False + + def is_pointer(self): + return not self.is_switch() and self.member_type.is_pointer() + + def is_array(self): + return not self.is_switch() and self.member_type.is_array() + + def is_struct(self): + return not self.is_switch() and self.member_type.is_struct() + + def is_primitive(self): + return not self.is_switch() and self.member_type.is_primitive() + + def has_attr(self, name): + if not name in valid_attributes: + raise Exception('attribute %s not expected' % name) + return name in self.attributes + + def has_minor_attr(self): + return self.has_attr("minor") + + def has_end_attr(self): + return self.has_attr("end") + + def get_minor_attr(self): + return self.attributes["minor"][0] + +class Member(Containee): + def __init__(self, name, member_type, attribute_list): + Containee.__init__(self) + self.name = name + self.member_type = member_type + self.attributes = fix_attributes(attribute_list) + + def resolve(self, container): + self.container = container + self.member_type = self.member_type.resolve() + self.member_type.register() + for i in propagated_attributes: + if self.has_attr(i): + self.member_type.attributes[i] = self.attributes[i] + return self + + def contains_member(self, member): + return self.member_type.contains_member(member) + + def is_primitive(self): + return self.member_type.is_primitive() + + def is_fixed_sizeof(self): + if self.has_end_attr(): + return False + return self.member_type.is_fixed_sizeof() + + def is_extra_size(self): + return self.has_end_attr() or self.has_attr("to_ptr") or self.member_type.is_extra_size() + + def is_fixed_nw_size(self): + if self.has_attr("virtual"): + return True + return self.member_type.is_fixed_nw_size() + + def get_fixed_nw_size(self): + if self.has_attr("virtual"): + return 0 + size = self.member_type.get_fixed_nw_size() + if self.has_minor_attr(): + minor = self.get_minor_attr() + size = FixedSize(size, minor) + return size + + def contains_extra_size(self): + return self.member_type.contains_extra_size() + + def sizeof(self): + return self.member_type.sizeof() + + def __repr__(self): + return "%s (%s)" % (str(self.name), str(self.member_type)) + + def get_num_pointers(self): + if self.has_attr("to_ptr"): + return 1 + return self.member_type.get_num_pointers() + + def get_pointer_names(self, marshalled): + if self.member_type.is_pointer(): + if self.has_attr("marshall") == marshalled: + names = [self.name] + else: + names = [] + else: + names = self.member_type.get_pointer_names(marshalled) + if self.has_attr("outvar"): + prefix = self.attributes["outvar"][0] + names = [prefix + "_" + name for name in names] + return names + +class SwitchCase: + def __init__(self, values, member): + self.values = values + self.member = member + self.members = [member] + + def get_check(self, var_cname, var_type): + checks = [] + for v in self.values: + if v == None: + return "1" + elif var_type.is_enum(): + checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v[1]))) + else: + checks.append("%s(%s & %s)" % (v[0], var_cname, var_type.c_enumname_by_name(v[1]))) + return " || ".join(checks) + + def resolve(self, container): + self.switch = container + self.member = self.member.resolve(self) + return self + + def get_num_pointers(self): + return self.member.get_num_pointers() + + def get_pointer_names(self, marshalled): + return self.member.get_pointer_names(marshalled) + +class Switch(Containee): + def __init__(self, variable, cases, name, attribute_list): + Containee.__init__(self) + self.variable = variable + self.name = name + self.cases = cases + self.attributes = fix_attributes(attribute_list) + + def is_switch(self): + return True + + def lookup_case_member(self, name): + for c in self.cases: + if c.member.name == name: + return c.member + return None + + def has_switch_member(self, member): + for c in self.cases: + if c.member == member: + return True + return False + + def resolve(self, container): + self.container = container + self.cases = [c.resolve(self) for c in self.cases] + return self + + def __repr__(self): + return "switch on %s %s" % (str(self.variable),str(self.name)) + + def is_fixed_sizeof(self): + # Kinda weird, but we're unlikely to have a real struct if there is an @end + if self.has_end_attr(): + return False + return True + + def is_fixed_nw_size(self): + if self.has_attr("fixedsize"): + return True + + size = None + has_default = False + for c in self.cases: + for v in c.values: + if v == None: + has_default = True + if not c.member.is_fixed_nw_size(): + return False + if size == None: + size = c.member.get_fixed_nw_size() + elif size != c.member.get_fixed_nw_size(): + return False + # Fixed size if all elements listed, or has default + if has_default: + return True + key = self.container.lookup_member(self.variable) + return len(self.cases) == len(key.member_type.values) + + def is_extra_size(self): + return self.has_end_attr() + + def contains_extra_size(self): + for c in self.cases: + if c.member.is_extra_size(): + return True + if c.member.contains_extra_size(): + return True + return False + + def get_fixed_nw_size(self): + if not self.is_fixed_nw_size(): + raise Exception("Not a fixed size type") + size = 0 + for c in self.cases: + size = max(size, c.member.get_fixed_nw_size()) + return size + + def sizeof(self): + return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(), + self.name) + + def contains_member(self, member): + return False # TODO: Don't support switch deep member lookup yet + + def get_num_pointers(self): + count = 0 + for c in self.cases: + count = max(count, c.get_num_pointers()) + return count + + def get_pointer_names(self, marshalled): + names = [] + for c in self.cases: + names = names + c.get_pointer_names(marshalled) + return names + +class ContainerType(Type): + def is_fixed_sizeof(self): + for m in self.members: + if not m.is_fixed_sizeof(): + return False + return True + + def contains_extra_size(self): + for m in self.members: + if m.is_extra_size(): + return True + if m.contains_extra_size(): + return True + return False + + def is_fixed_nw_size(self): + for i in self.members: + if not i.is_fixed_nw_size(): + return False + return True + + def get_fixed_nw_size(self): + size = 0 + for i in self.members: + size = size + i.get_fixed_nw_size() + return size + + def contains_member(self, member): + for m in self.members: + if m == member or m.contains_member(member): + return True + return False + + def get_fixed_nw_offset(self, member): + size = 0 + for i in self.members: + if i == member: + break + if i.contains_member(member): + size = size + i.member_type.get_fixed_nw_offset(member) + break + if i.is_fixed_nw_size(): + size = size + i.get_fixed_nw_size() + return size + + def resolve(self): + self.members = [m.resolve(self) for m in self.members] + return self + + def get_num_pointers(self): + count = 0 + for m in self.members: + count = count + m.get_num_pointers() + return count + + def get_pointer_names(self, marshalled): + names = [] + for m in self.members: + names = names + m.get_pointer_names(marshalled) + return names + + def get_nw_offset(self, member, prefix = "", postfix = ""): + fixed = self.get_fixed_nw_offset(member) + v = [] + container = self + while container != None: + members = container.members + container = None + for m in members: + if m == member: + break + if m.contains_member(member): + container = m.member_type + break + if m.is_switch() and m.has_switch_member(member): + break + if not m.is_fixed_nw_size(): + v.append(prefix + m.name + postfix) + if len(v) > 0: + return str(fixed) + " + " + (" + ".join(v)) + else: + return str(fixed) + + def lookup_member(self, name): + dot = name.find('.') + rest = None + if dot >= 0: + rest = name[dot+1:] + name = name[:dot] + + member = None + if name in self.members_by_name: + member = self.members_by_name[name] + else: + for m in self.members: + if m.is_switch(): + member = m.lookup_case_member(name) + if member != None: + break + if member != None: + break + + if member == None: + raise Exception("No member called %s found" % name) + + if rest != None: + return member.member_type.lookup_member(rest) + + return member + +class StructType(ContainerType): + def __init__(self, name, members, attribute_list): + Type.__init__(self) + self.name = name + self.members = members + self.members_by_name = {} + for m in members: + self.members_by_name[m.name] = m + self.attributes = fix_attributes(attribute_list) + + def __str__(self): + if self.name == None: + return "anonymous struct" + else: + return "struct %s" % self.name + + def c_type(self): + if self.has_attr("ctype"): + return self.attributes["ctype"][0] + return codegen.prefix_camel(self.name) + +class MessageType(ContainerType): + def __init__(self, name, members, attribute_list): + Type.__init__(self) + self.name = name + self.members = members + self.members_by_name = {} + for m in members: + self.members_by_name[m.name] = m + self.reverse_members = {} # ChannelMembers referencing this message + self.attributes = fix_attributes(attribute_list) + + def __str__(self): + if self.name == None: + return "anonymous message" + else: + return "message %s" % self.name + + def c_name(self): + if self.name == None: + cms = list(self.reverse_members.keys()) + if len(cms) != 1: + raise "Unknown typename for message" + cm = cms[0] + channelname = cm.channel.member_name + if channelname == None: + channelname = "" + else: + channelname = channelname + "_" + if cm.is_server: + return "msg_" + channelname + cm.name + else: + return "msgc_" + channelname + cm.name + else: + return codegen.prefix_camel("Msg", self.name) + + def c_type(self): + if self.has_attr("ctype"): + return self.attributes["ctype"][0] + if self.name == None: + cms = list(self.reverse_members.keys()) + if len(cms) != 1: + raise "Unknown typename for message" + cm = cms[0] + channelname = cm.channel.member_name + if channelname == None: + channelname = "" + if cm.is_server: + return codegen.prefix_camel("Msg", channelname, cm.name) + else: + return codegen.prefix_camel("Msgc", channelname, cm.name) + else: + return codegen.prefix_camel("Msg", self.name) + +class ChannelMember(Containee): + def __init__(self, name, message_type, value): + Containee.__init__(self) + self.name = name + self.message_type = message_type + self.value = value + + def resolve(self, channel): + self.channel = channel + self.message_type = self.message_type.resolve() + self.message_type.reverse_members[self] = 1 + + return self + + def __repr__(self): + return "%s (%s)" % (str(self.name), str(self.message_type)) + +class ChannelType(Type): + def __init__(self, name, base, members, attribute_list): + Type.__init__(self) + self.name = name + self.base = base + self.member_name = None + self.members = members + self.attributes = fix_attributes(attribute_list) + + def __str__(self): + if self.name == None: + return "anonymous channel" + else: + return "channel %s" % self.name + + def is_fixed_nw_size(self): + return False + + def get_client_message(self, name): + return self.client_messages_byname[name] + + def get_server_message(self, name): + return self.server_messages_byname[name] + + def resolve(self): + if self.base != None: + self.base = self.base.resolve() + + server_messages = self.base.server_messages[:] + server_messages_byname = self.base.server_messages_byname.copy() + client_messages = self.base.client_messages[:] + client_messages_byname = self.base.client_messages_byname.copy() + + # Set default member_name, FooChannel -> foo + self.member_name = self.name[:-7].lower() + else: + server_messages = [] + server_messages_byname = {} + client_messages = [] + client_messages_byname = {} + + server_count = 1 + client_count = 1 + + server = True + for m in self.members: + if m == "server": + server = True + elif m == "client": + server = False + elif server: + m.is_server = True + m = m.resolve(self) + if m.value: + server_count = m.value + 1 + else: + m.value = server_count + server_count = server_count + 1 + server_messages.append(m) + server_messages_byname[m.name] = m + else: + m.is_server = False + m = m.resolve(self) + if m.value: + client_count = m.value + 1 + else: + m.value = client_count + client_count = client_count + 1 + client_messages.append(m) + client_messages_byname[m.name] = m + + self.server_messages = server_messages + self.server_messages_byname = server_messages_byname + self.client_messages = client_messages + self.client_messages_byname = client_messages_byname + + return self + +class ProtocolMember: + def __init__(self, name, channel_type, value): + self.name = name + self.channel_type = channel_type + self.value = value + + def resolve(self, protocol): + self.channel_type = self.channel_type.resolve() + self.channel_type.member_name = self.name + return self + + def __repr__(self): + return "%s (%s)" % (str(self.name), str(self.channel_type)) + +class ProtocolType(Type): + def __init__(self, name, channels): + Type.__init__(self) + self.name = name + self.channels = channels + + def __str__(self): + if self.name == None: + return "anonymous protocol" + else: + return "protocol %s" % self.name + + def is_fixed_nw_size(self): + return False + + def resolve(self): + count = 1 + for m in self.channels: + m = m.resolve(self) + if m.value: + count = m.value + 1 + else: + m.value = count + count = count + 1 + + return self + +class FdType(IntegerType): + def __init__(self): + IntegerType.__init__(self, 0, False) + self.name = "fd" + + def c_type(self): + return "int" + +int8 = IntegerType(8, True) +uint8 = IntegerType(8, False) +int16 = IntegerType(16, True) +uint16 = IntegerType(16, False) +int32 = IntegerType(32, True) +uint32 = IntegerType(32, False) +int64 = IntegerType(64, True) +uint64 = IntegerType(64, False) +unix_fd = FdType() diff --git a/spice-common/python_modules/spice_parser.py b/spice-common/python_modules/spice_parser.py new file mode 100644 index 0000000..db3cc8d --- /dev/null +++ b/spice-common/python_modules/spice_parser.py @@ -0,0 +1,163 @@ +import six + +try: + from pyparsing import Literal, CaselessLiteral, Word, OneOrMore, ZeroOrMore, \ + Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \ + alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith +except ImportError: + six.print_("Module pyparsing not found.") + exit(1) + + +from . import ptypes +import sys + +cvtInt = lambda toks: int(toks[0]) + +def parseVariableDef(toks): + t = toks[0][0] + pointer = toks[0][1] + name = toks[0][2] + array_size = toks[0][3] + attributes = toks[0][4] + + if array_size != None: + t = ptypes.ArrayType(t, array_size) + + if pointer != None: + t = ptypes.PointerType(t) + + return ptypes.Member(name, t, attributes) + +bnf = None +def SPICE_BNF(): + global bnf + + if not bnf: + + # punctuation + colon = Literal(":").suppress() + lbrace = Literal("{").suppress() + rbrace = Literal("}").suppress() + lbrack = Literal("[").suppress() + rbrack = Literal("]").suppress() + lparen = Literal("(").suppress() + rparen = Literal(")").suppress() + equals = Literal("=").suppress() + comma = Literal(",").suppress() + semi = Literal(";").suppress() + + # primitive types + int8_ = Keyword("int8").setParseAction(replaceWith(ptypes.int8)) + uint8_ = Keyword("uint8").setParseAction(replaceWith(ptypes.uint8)) + int16_ = Keyword("int16").setParseAction(replaceWith(ptypes.int16)) + uint16_ = Keyword("uint16").setParseAction(replaceWith(ptypes.uint16)) + int32_ = Keyword("int32").setParseAction(replaceWith(ptypes.int32)) + uint32_ = Keyword("uint32").setParseAction(replaceWith(ptypes.uint32)) + int64_ = Keyword("int64").setParseAction(replaceWith(ptypes.int64)) + uint64_ = Keyword("uint64").setParseAction(replaceWith(ptypes.uint64)) + unix_fd_ = Keyword("unix_fd").setParseAction(replaceWith(ptypes.unix_fd)) + + # keywords + enum32_ = Keyword("enum32").setParseAction(replaceWith(32)) + enum16_ = Keyword("enum16").setParseAction(replaceWith(16)) + enum8_ = Keyword("enum8").setParseAction(replaceWith(8)) + flags32_ = Keyword("flags32").setParseAction(replaceWith(32)) + flags16_ = Keyword("flags16").setParseAction(replaceWith(16)) + flags8_ = Keyword("flags8").setParseAction(replaceWith(8)) + channel_ = Keyword("channel") + server_ = Keyword("server") + client_ = Keyword("client") + protocol_ = Keyword("protocol") + typedef_ = Keyword("typedef") + struct_ = Keyword("struct") + message_ = Keyword("message") + image_size_ = Keyword("image_size") + bytes_ = Keyword("bytes") + cstring_ = Keyword("cstring") + switch_ = Keyword("switch") + default_ = Keyword("default") + case_ = Keyword("case") + + identifier = Word( alphas, alphanums + "_" ) + enumname = Word( alphanums + "_" ) + + integer = ( Combine( CaselessLiteral("0x") + Word( nums+"abcdefABCDEF" ) ) | + Word( nums+"+-", nums ) ).setName("int").setParseAction(cvtInt) + + typename = identifier.copy().setParseAction(lambda toks : ptypes.TypeRef(str(toks[0]))) + + # This is just normal "types", i.e. not channels or messages + typeSpec = Forward() + + attributeValue = integer ^ identifier + attribute = Group(Combine ("@" + identifier) + Optional(lparen + delimitedList(attributeValue) + rparen)) + attributes = Group(ZeroOrMore(attribute)) + arraySizeSpecImage = Group(image_size_ + lparen + integer + comma + identifier + comma + identifier + rparen) + arraySizeSpecBytes = Group(bytes_ + lparen + identifier + comma + identifier + rparen) + arraySizeSpecCString = Group(cstring_ + lparen + rparen) + arraySizeSpec = lbrack + Optional(identifier ^ integer ^ arraySizeSpecImage ^ arraySizeSpecBytes ^arraySizeSpecCString, default="") + rbrack + variableDef = Group(typeSpec + Optional("*", default=None) + identifier + Optional(arraySizeSpec, default=None) + attributes - semi) \ + .setParseAction(parseVariableDef) + + switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | Group(case_.suppress() + Optional("!", default="") + identifier) + colon)) + variableDef) \ + .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1])) + switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \ + .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4])) + messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace) + structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3])) + + # have to use longest match for type, in case a user-defined type name starts with a keyword type, like "channel_type" + typeSpec << ( structSpec ^ int8_ ^ uint8_ ^ int16_ ^ uint16_ ^ + int32_ ^ uint32_ ^ int64_ ^ uint64_ ^ unix_fd_ ^ + typename).setName("type") + + flagsBody = enumBody = Group(lbrace + delimitedList(Group (enumname + Optional(equals + integer))) + Optional(comma) + rbrace) + + messageSpec = Group(message_ + messageBody + attributes).setParseAction(lambda toks: ptypes.MessageType(None, toks[0][1], toks[0][2])) | typename + + channelParent = Optional(colon + typename, default=None) + channelMessage = Group(messageSpec + identifier + Optional(equals + integer, default=None) + semi) \ + .setParseAction(lambda toks: ptypes.ChannelMember(toks[0][1], toks[0][0], toks[0][2])) + channelBody = channelParent + Group(lbrace + ZeroOrMore( server_ + colon | client_ + colon | channelMessage) + rbrace) + + enum_ = (enum32_ | enum16_ | enum8_) + flags_ = (flags32_ | flags16_ | flags8_) + enumDef = Group(enum_ + identifier + enumBody + attributes - semi).setParseAction(lambda toks: ptypes.EnumType(toks[0][0], toks[0][1], toks[0][2], toks[0][3])) + flagsDef = Group(flags_ + identifier + flagsBody + attributes - semi).setParseAction(lambda toks: ptypes.FlagsType(toks[0][0], toks[0][1], toks[0][2], toks[0][3])) + messageDef = Group(message_ + identifier + messageBody + attributes - semi).setParseAction(lambda toks: ptypes.MessageType(toks[0][1], toks[0][2], toks[0][3])) + channelDef = Group(channel_ + identifier + channelBody + attributes - semi).setParseAction(lambda toks: ptypes.ChannelType(toks[0][1], toks[0][2], toks[0][3], toks[0][4])) + structDef = Group(struct_ + identifier + structBody + attributes - semi).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3])) + typedefDef = Group(typedef_ + identifier + typeSpec + attributes - semi).setParseAction(lambda toks: ptypes.TypeAlias(toks[0][1], toks[0][2], toks[0][3])) + + definitions = typedefDef | structDef | enumDef | flagsDef | messageDef | channelDef + + protocolChannel = Group(typename + identifier + Optional(equals + integer, default=None) + semi) \ + .setParseAction(lambda toks: ptypes.ProtocolMember(toks[0][1], toks[0][0], toks[0][2])) + protocolDef = Group(protocol_ + identifier + Group(lbrace + ZeroOrMore(protocolChannel) + rbrace) + semi) \ + .setParseAction(lambda toks: ptypes.ProtocolType(toks[0][1], toks[0][2])) + + bnf = ZeroOrMore (definitions) + protocolDef + StringEnd() + + singleLineComment = "//" + restOfLine + bnf.ignore( singleLineComment ) + bnf.ignore( cStyleComment ) + + return bnf + + +def parse(filename): + try: + bnf = SPICE_BNF() + types = bnf.parseFile(filename) + except ParseException as err: + six.print_(err.line, file=sys.stderr) + six.print_(" "*(err.column-1) + "^", file=sys.stderr) + six.print_(err, file=sys.stderr) + return None + + for t in types: + t.resolve() + t.register() + protocol = types[-1] + return protocol diff --git a/spice-common/spice.proto b/spice-common/spice.proto new file mode 100644 index 0000000..d21510d --- /dev/null +++ b/spice-common/spice.proto @@ -0,0 +1,1414 @@ +/* built in types: + int8, uint8, 16, 32, 64 +*/ + +typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); + +struct Point { + int32 x; + int32 y; +}; + +struct Point16 { + int16 x; + int16 y; +}; + +struct PointFix { + fixed28_4 x; + fixed28_4 y; +}; + +struct Rect { + int32 top; + int32 left; + int32 bottom; + int32 right; +}; + +struct Transform { + uint32 t00; + uint32 t01; + uint32 t02; + uint32 t10; + uint32 t11; + uint32 t12; +}; + +enum32 link_err { + OK, + ERROR, + INVALID_MAGIC, + INVALID_DATA, + VERSION_MISMATCH, + NEED_SECURED, + NEED_UNSECURED, + PERMISSION_DENIED, + BAD_CONNECTION_ID, + CHANNEL_NOT_AVAILABLE +}; + +enum32 warn_code { + WARN_GENERAL +} @prefix(SPICE_); + +enum32 info_code { + INFO_GENERAL +} @prefix(SPICE_); + +flags32 migrate_flags { + NEED_FLUSH, + NEED_DATA_TRANSFER +} @prefix(SPICE_MIGRATE_); + +flags32 composite_flags { + OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7, + SRC_FILTER0, SRC_FILTER1, SRC_FILTER2, + MASK_FILTER0, MASK_FITLER1, MASK_FILTER2, + + SRC_REPEAT0, SRC_REPEAT1, + MASK_REPEAT0, MASK_REPEAT1, + COMPONENT_ALPHA, + + HAS_MASK, + HAS_SRC_TRANSFORM, + HAS_MASK_TRANSFORM, + + /* These are used to override the formats given in the images. For + * example, if the mask image has format a8r8g8b8, but MASK_OPAQUE + * is set, the image should be treated as if it were x8r8g8b8 + */ + SOURCE_OPAQUE, + MASK_OPAQUE, + DEST_OPAQUE, +} @prefix(SPICE_COMPOSITE_); + +enum32 notify_severity { + INFO, + WARN, + ERROR, +}; + +enum32 notify_visibility { + LOW, + MEDIUM, + HIGH, +}; + +flags16 mouse_mode { + SERVER, + CLIENT, +}; + +enum16 pubkey_type { + INVALID, + RSA, + RSA2, + DSA, + DSA1, + DSA2, + DSA3, + DSA4, + DH, + EC, +}; + +message Empty { +}; + +message Data { + uint8 data[] @end @ctype(uint8_t); +} @nocopy; + +struct ChannelWait { + uint8 channel_type; + uint8 channel_id; + uint64 message_serial; +} @ctype(SpiceWaitForChannel); + +channel BaseChannel { + server: + message { + migrate_flags flags; + } migrate; + + Data migrate_data; + + message { + uint32 generation; + uint32 window; + } set_ack; + + message { + uint32 id; + uint64 timestamp; + uint8 data[] @ctype(uint8_t) @as_ptr(data_len); + } ping; + + message { + uint8 wait_count; + ChannelWait wait_list[wait_count] @end; + } wait_for_channels; + + message { + uint64 time_stamp; + link_err reason; + } @ctype(SpiceMsgDisconnect) disconnecting; + + message { + uint64 time_stamp; + notify_severity severity; + notify_visibility visibilty; + uint32 what; /* error_code/warn_code/info_code */ + uint32 message_len; + uint8 message[message_len] @end @nomarshal; + } notify; + + Data list; /* the msg body is SpiceSubMessageList */ + + Empty base_last = 100; + + client: + message { + uint32 generation; + } ack_sync; + + Empty ack; + + message { + uint32 id; + uint64 timestamp; + } @ctype(SpiceMsgPing) pong; + + Empty migrate_flush_mark; + + Data migrate_data; + + message { + uint64 time_stamp; + link_err reason; + } @ctype(SpiceMsgDisconnect) disconnecting; +}; + +struct ChannelId { + uint8 type; + uint8 id; +}; + +struct DstInfo { + uint16 port; + uint16 sport; + uint32 host_size; + uint8 *host_data[host_size] @zero_terminated @marshall @nonnull; + uint32 cert_subject_size; + uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; +} @ctype(SpiceMigrationDstInfo); + +channel MainChannel : BaseChannel { + server: + message { + DstInfo dst_info; + } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101; + + Empty migrate_cancel; + + message { + uint32 session_id; + uint32 display_channels_hint; + uint32 supported_mouse_modes; + uint32 current_mouse_mode; + uint32 agent_connected; + uint32 agent_tokens; + uint32 multi_media_time; + uint32 ram_hint; + } init; + + message { + uint32 num_of_channels; + ChannelId channels[num_of_channels] @end; + } @ctype(SpiceMsgChannels) channels_list; + + message { + mouse_mode supported_modes; + mouse_mode current_mode @unique_flag; + } mouse_mode; + + message { + uint32 time; + } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time; + + Empty agent_connected; + + message { + link_err error_code; + } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected; + + Data agent_data; + + message { + uint32 num_tokens; + } @ctype(SpiceMsgMainAgentTokens) agent_token; + + message { + uint16 port; + uint16 sport; + uint32 host_size; + uint8 *host_data[host_size] @zero_terminated @marshall; + uint32 cert_subject_size; + uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; + } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host; + + Empty migrate_end; + + message { + uint32 name_len; + uint8 name[name_len] @end; + } name; + + message { + uint8 uuid[16]; + } uuid; + + message { + uint32 num_tokens; + } agent_connected_tokens; + + message { + DstInfo dst_info; + uint32 src_mig_version; + } migrate_begin_seamless; + + Empty migrate_dst_seamless_ack; + Empty migrate_dst_seamless_nack; + + client: + message { + uint64 cache_size; + } @ctype(SpiceMsgcClientInfo) client_info = 101; + + Empty migrate_connected; + + Empty migrate_connect_error; + + Empty attach_channels; + + message { + mouse_mode mode; + } mouse_mode_request; + + message { + uint32 num_tokens; + } agent_start; + + Data agent_data; + + message { + uint32 num_tokens; + } @ctype(SpiceMsgcMainAgentTokens) agent_token; + + Empty migrate_end; + + message { + uint32 src_version; + } migrate_dst_do_seamless; + + Empty migrate_connected_seamless; +}; + +enum8 clip_type { + NONE, + RECTS +}; + +flags8 path_flags { /* TODO: C enum names changes */ + BEGIN = 0, + END = 1, + CLOSE = 3, + BEZIER = 4, +} @prefix(SPICE_PATH_); + +enum8 video_codec_type { + MJPEG = 1, + VP8, + H264, +}; + +flags8 stream_flags { + TOP_DOWN = 0, +}; + +enum8 brush_type { + NONE, + SOLID, + PATTERN, +}; + +flags8 mask_flags { + INVERS, +}; + +enum8 image_type { + BITMAP, + QUIC, + RESERVED, + LZ_PLT = 100, + LZ_RGB, + GLZ_RGB, + FROM_CACHE, + SURFACE, + JPEG, + FROM_CACHE_LOSSLESS, + ZLIB_GLZ_RGB, + JPEG_ALPHA, + LZ4, +}; + +enum8 image_compression { + INVALID = 0, + OFF, + AUTO_GLZ, + AUTO_LZ, + QUIC, + GLZ, + LZ, + LZ4, +}; + +flags8 image_flags { + CACHE_ME, + HIGH_BITS_SET, + CACHE_REPLACE_ME, +}; + +enum8 bitmap_fmt { + INVALID, + 1BIT_LE, + 1BIT_BE, + 4BIT_LE, + 4BIT_BE, + 8BIT /* 8bit indexed mode */, + 16BIT, /* 0555 mode */ + 24BIT /* 3 byte, brg */, + 32BIT /* 4 byte, xrgb in little endian format */, + RGBA /* 4 byte, argb in little endian format */, + 8BIT_A /* 1 byte, alpha */ +}; + +flags8 bitmap_flags { + PAL_CACHE_ME, + PAL_FROM_CACHE, + TOP_DOWN, +}; + +flags8 jpeg_alpha_flags { + TOP_DOWN, +}; + +enum8 image_scale_mode { + INTERPOLATE, + NEAREST, +}; + +flags16 ropd { + INVERS_SRC, + INVERS_BRUSH, + INVERS_DEST, + OP_PUT, + OP_OR, + OP_AND, + OP_XOR, + OP_BLACKNESS, + OP_WHITENESS, + OP_INVERS, + INVERS_RES, +}; + +/* This *must* remain with values identical to api/winddi.h + LA_STYLED == 0x8 (log_2)=> 3 + LA_STARTGAP == 0x4 (log_2)=> 2 + This is used by the windows driver. + */ +flags8 line_flags { + STYLED = 3, + START_WITH_GAP = 2, +}; + +flags8 string_flags { + RASTER_A1, + RASTER_A4, + RASTER_A8, + RASTER_TOP_DOWN, +}; + +flags32 surface_flags { + /* Adding flags requires some caps check, since old clients only + treat the value as an enum and not as a flag (flag == PRIMARY) */ + PRIMARY +}; + +enum32 surface_fmt { + INVALID, + 1_A = 1, + 8_A = 8, + 16_555 = 16 , + 16_565 = 80, + 32_xRGB = 32, + 32_ARGB = 96 +}; + +flags8 alpha_flags { + DEST_HAS_ALPHA, + SRC_SURFACE_HAS_ALPHA +}; + +enum8 resource_type { + INVALID, + PIXMAP +} @prefix(SPICE_RES_TYPE_); + +struct ClipRects { + uint32 num_rects; + Rect rects[num_rects] @end; +}; + +struct PathSegment { + path_flags flags; + uint32 count; + PointFix points[count] @end; +} @ctype(SpicePathSeg); + +struct Path { + uint32 num_segments; + PathSegment segments[num_segments] @ptr_array; +}; + +struct Clip { + clip_type type; + switch (type) { + case RECTS: + ClipRects rects @outvar(cliprects) @to_ptr; + } u @anon; +}; + +struct DisplayBase { + uint32 surface_id; + Rect box; + Clip clip; +} @ctype(SpiceMsgDisplayBase); + +struct ResourceID { + uint8 type; + uint64 id; +}; + +struct WaitForChannel { + uint8 channel_type; + uint8 channel_id; + uint64 message_serial; +}; + +struct Palette { + uint64 unique; + uint16 num_ents; + uint32 ents[num_ents] @end; +}; + +struct BitmapData { + bitmap_fmt format; + bitmap_flags flags; + uint32 x; + uint32 y; + uint32 stride; + switch (flags) { + case PAL_FROM_CACHE: + uint64 palette_id; + default: + Palette *palette @outvar(bitmap); + } pal @anon; + uint8 data[image_size(8, stride, y)] @chunk @nomarshal; +} @ctype(SpiceBitmap); + +struct BinaryData { + uint32 data_size; + uint8 data[data_size] @nomarshal @chunk; +} @ctype(SpiceQUICData); + +struct LZPLTData { + bitmap_flags flags; + uint32 data_size; + switch (flags) { + case PAL_FROM_CACHE: + uint64 palette_id; + default: + Palette *palette @nonnull @outvar(lzplt); + } pal @anon; + uint8 data[data_size] @nomarshal @chunk; +}; + +struct ZlibGlzRGBData { + uint32 glz_data_size; + uint32 data_size; + uint8 data[data_size] @nomarshal @chunk; +} @ctype(SpiceZlibGlzRGBData); + +struct JPEGAlphaData { + jpeg_alpha_flags flags; + uint32 jpeg_size; + uint32 data_size; + uint8 data[data_size] @nomarshal @chunk; +} @ctype(SpiceJPEGAlphaData); + +struct Surface { + uint32 surface_id; +}; + + +struct Image { + struct ImageDescriptor { + uint64 id; + image_type type; + image_flags flags; + uint32 width; + uint32 height; + } descriptor; + + switch (descriptor.type) { + case BITMAP: + BitmapData bitmap; + case QUIC: + BinaryData quic; + case LZ_RGB: + case GLZ_RGB: + BinaryData lz_rgb; + case JPEG: + BinaryData jpeg; + case LZ4: + BinaryData lz4; + case LZ_PLT: + LZPLTData lz_plt; + case ZLIB_GLZ_RGB: + ZlibGlzRGBData zlib_glz; + case JPEG_ALPHA: + JPEGAlphaData jpeg_alpha; + case SURFACE: + Surface surface; + } u; +}; + +struct Pattern { + Image *pat @nonnull; + Point pos; +}; + +struct Brush { + brush_type type; + switch (type) { + case SOLID: + uint32 color; + case PATTERN: + Pattern pattern; + } u; +}; + +struct QMask { + mask_flags flags; + Point pos; + Image *bitmap; +}; + +struct LineAttr { + line_flags flags; + switch (flags) { + case STYLED: + uint8 style_nseg; + } u1 @anon; + switch (flags) { + case STYLED: + fixed28_4 *style[style_nseg]; + } u2 @anon; +}; + +struct RasterGlyphA1 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(1, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct RasterGlyphA4 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(4, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct RasterGlyphA8 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(8, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct String { + uint16 length; + string_flags flags; /* Special: Only one of a1/a4/a8 set */ + switch (flags) { + case RASTER_A1: + RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + case RASTER_A4: + RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + case RASTER_A8: + RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + } u @anon; +}; + +struct StreamDataHeader { + uint32 id; + uint32 multi_media_time; +}; + +struct Head { + uint32 id; + uint32 surface_id; + uint32 width; + uint32 height; + uint32 x; + uint32 y; + uint32 flags; +}; + +flags32 gl_scanout_flags { + Y0TOP +}; + +channel DisplayChannel : BaseChannel { + server: + message { + uint32 x_res; + uint32 y_res; + uint32 bits; + } mode = 101; + + Empty mark; + Empty reset; + message { + DisplayBase base; + Point src_pos; + } copy_bits; + + message { + uint16 count; + ResourceID resources[count] @end; + } @ctype(SpiceResourceList) inval_list; + + message { + uint8 wait_count; + WaitForChannel wait_list[wait_count] @end; + } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps; + + message { + uint64 id; + } @ctype(SpiceMsgDisplayInvalOne) inval_palette; + + Empty inval_all_palettes; + + message { + uint32 surface_id; + uint32 id; + stream_flags flags; + video_codec_type codec_type; + uint64 stamp; + uint32 stream_width; + uint32 stream_height; + uint32 src_width; + uint32 src_height; + Rect dest; + Clip clip; + } stream_create = 122; + + message { + StreamDataHeader base; + uint32 data_size; + uint8 data[data_size] @end @nomarshal; + } stream_data; + + message { + uint32 id; + Clip clip; + } stream_clip; + + message { + uint32 id; + } stream_destroy; + + Empty stream_destroy_all; + + message { + DisplayBase base; + struct Fill { + Brush brush @outvar(brush); + ropd rop_descriptor; + QMask mask @outvar(mask); + } data; + } draw_fill = 302; + + message { + DisplayBase base; + struct Opaque { + Image *src_bitmap; + Rect src_area; + Brush brush; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_opaque; + + message { + DisplayBase base; + struct Copy { + Image *src_bitmap; + Rect src_area; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_copy; + + message { + DisplayBase base; + struct Blend { + Image *src_bitmap; + Rect src_area; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } @ctype(SpiceCopy) data; + } draw_blend; + + message { + DisplayBase base; + struct Blackness { + QMask mask @outvar(mask); + } data; + } draw_blackness; + + message { + DisplayBase base; + struct Whiteness { + QMask mask @outvar(mask); + } data; + } draw_whiteness; + + message { + DisplayBase base; + struct Invers { + QMask mask @outvar(mask); + } data; + } draw_invers; + + message { + DisplayBase base; + struct Rop3 { + Image *src_bitmap; + Rect src_area; + Brush brush; + uint8 rop3; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_rop3; + + message { + DisplayBase base; + struct Stroke { + Path *path @marshall @nonnull; + LineAttr attr; + Brush brush; + uint16 fore_mode; + uint16 back_mode; + } data; + } draw_stroke; + + message { + DisplayBase base; + struct Text { + String *str @marshall @nonnull; + Rect back_area; + Brush fore_brush @outvar(fore_brush); + Brush back_brush @outvar(back_brush); + uint16 fore_mode; + uint16 back_mode; + } data; + } draw_text; + + message { + DisplayBase base; + struct Transparent { + Image *src_bitmap; + Rect src_area; + uint32 src_color; + uint32 true_color; + } data; + } draw_transparent; + + message { + DisplayBase base; + struct AlphaBlend { + alpha_flags alpha_flags; + uint8 alpha; + Image *src_bitmap; + Rect src_area; + } data; + } draw_alpha_blend; + + message { + uint32 surface_id; + uint32 width; + uint32 height; + surface_fmt format; + surface_flags flags; + } @ctype(SpiceMsgSurfaceCreate) surface_create; + + message { + uint32 surface_id; + } @ctype(SpiceMsgSurfaceDestroy) surface_destroy; + + message { + StreamDataHeader base; + uint32 width; + uint32 height; + Rect dest; + uint32 data_size; + uint8 data[data_size] @end @nomarshal; + } stream_data_sized; + + message { + uint16 count; + uint16 max_allowed; + Head heads[count] @end; + } monitors_config; + + message { + DisplayBase base; + struct Composite { + composite_flags flags; + Image *src_bitmap; + switch (flags) { + case HAS_MASK: + Image *mask_bitmap; + } a @anon; + switch (flags) { + case HAS_SRC_TRANSFORM: + Transform src_transform; + } b @anon; + switch (flags) { + case HAS_MASK_TRANSFORM: + Transform mask_transform; + } c @anon; + Point16 src_origin; + Point16 mask_origin; + } data; + } draw_composite; + + message { + uint32 stream_id; + uint32 unique_id; + uint32 max_window_size; + uint32 timeout_ms; + } stream_activate_report; + + message { + unix_fd drm_dma_buf_fd; + uint32 width; + uint32 height; + uint32 stride; + /* specifies the format of drm_dma_buf_fd defined in drm_fourcc.h */ + uint32 drm_fourcc_format; + gl_scanout_flags flags; + } gl_scanout_unix; + + message { + uint32 x; + uint32 y; + uint32 w; + uint32 h; + } gl_draw; + + client: + message { + uint8 pixmap_cache_id; + int64 pixmap_cache_size; //in pixels + uint8 glz_dictionary_id; + int32 glz_dictionary_window_size; // in pixels + } init = 101; + + message { + uint32 stream_id; + uint32 unique_id; + uint32 start_frame_mm_time; + uint32 end_frame_mm_time; + uint32 num_frames; + uint32 num_drops; + int32 last_frame_delay; + uint32 audio_delay; + } stream_report; + + message { + image_compression image_compression; + } preferred_compression; + + message { + } gl_draw_done; +}; + +flags16 keyboard_modifier_flags { + SCROLL_LOCK, + NUM_LOCK, + CAPS_LOCK +}; + +enum8 mouse_button { + INVALID, + LEFT, + MIDDLE, + RIGHT, + UP, + DOWN, +}; + +flags16 mouse_button_mask { + LEFT, + MIDDLE, + RIGHT +}; + +channel InputsChannel : BaseChannel { + client: + message { + uint32 code; + } @ctype(SpiceMsgcKeyDown) key_down = 101; + + message { + uint32 code; + } @ctype(SpiceMsgcKeyUp) key_up; + + message { + keyboard_modifier_flags modifiers; + } @ctype(SpiceMsgcKeyModifiers) key_modifiers; + + Data key_scancode; + + message { + int32 dx; + int32 dy; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111; + + message { + uint32 x; + uint32 y; + mouse_button_mask buttons_state; + uint8 display_id; + } @ctype(SpiceMsgcMousePosition) mouse_position; + + message { + mouse_button button; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMousePress) mouse_press; + + message { + mouse_button button; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMouseRelease) mouse_release; + + server: + message { + keyboard_modifier_flags keyboard_modifiers; + } init = 101; + + message { + keyboard_modifier_flags modifiers; + } key_modifiers; + + Empty mouse_motion_ack = 111; +}; + +enum8 cursor_type { + ALPHA, + MONO, + COLOR4, + COLOR8, + COLOR16, + COLOR24, + COLOR32, +}; + +flags16 cursor_flags { + NONE, /* Means no cursor */ + CACHE_ME, + FROM_CACHE, +}; + +struct CursorHeader { + uint64 unique; + cursor_type type; + uint16 width; + uint16 height; + uint16 hot_spot_x; + uint16 hot_spot_y; +}; + +struct Cursor { + cursor_flags flags; + switch (flags) { + case !NONE: + CursorHeader header; + } u @anon; + uint8 data[] @as_ptr(data_size); +}; + +channel CursorChannel : BaseChannel { + server: + message { + Point16 position; + uint16 trail_length; + uint16 trail_frequency; + uint8 visible; + Cursor cursor; + } init = 101; + + Empty reset; + + message { + Point16 position; + uint8 visible; + Cursor cursor; + } set; + + message { + Point16 position; + } move; + + Empty hide; + + message { + uint16 length; + uint16 frequency; + } trail; + + message { + uint64 id; + } @ctype(SpiceMsgDisplayInvalOne) inval_one; + + Empty inval_all; +}; + +enum16 audio_data_mode { + INVALID, + RAW, + CELT_0_5_1, + OPUS, +}; + +enum16 audio_fmt { + INVALID, + S16, +}; + +message AudioVolume { + uint8 nchannels; + uint16 volume[nchannels] @end; +}; + +message AudioMute { + uint8 mute; +}; + +channel PlaybackChannel : BaseChannel { + server: + message { + uint32 time; + uint8 data[] @as_ptr(data_size); + } @ctype(SpiceMsgPlaybackPacket) data = 101; + + message { + uint32 time; + audio_data_mode mode; + uint8 data[] @as_ptr(data_size); + } mode; + + message { + uint32 channels; + audio_fmt format; + uint32 frequency; + uint32 time; + } start; + + Empty stop; + AudioVolume volume; + AudioMute mute; + + message { + uint32 latency_ms; + } latency; +}; + +channel RecordChannel : BaseChannel { + server: + message { + uint32 channels; + audio_fmt format; + uint32 frequency; + } start = 101; + + Empty stop; + AudioVolume volume; + AudioMute mute; + client: + message { + uint32 time; + uint8 data[] @nomarshal @as_ptr(data_size); + } @ctype(SpiceMsgcRecordPacket) data = 101; + + message { + uint32 time; + audio_data_mode mode; + uint8 data[] @as_ptr(data_size); + } mode; + + message { + uint32 time; + } start_mark; +}; + +enum16 tunnel_service_type { + INVALID, + GENERIC, + IPP, +}; + +enum16 tunnel_ip_type { + INVALID, + IPv4, +}; + +struct TunnelIpInfo { + tunnel_ip_type type; + switch (type) { + case IPv4: + uint8 ipv4[4]; + } u; +} @ctype(SpiceMsgTunnelIpInfo); + +channel TunnelChannel : BaseChannel { + server: + message { + uint16 max_num_of_sockets; + uint32 max_socket_data_size; + } init = 101; + + message { + uint32 service_id; + TunnelIpInfo virtual_ip; + } service_ip_map; + + message { + uint16 connection_id; + uint32 service_id; + uint32 tokens; + } socket_open; + + message { + uint16 connection_id; + } socket_fin; + + message { + uint16 connection_id; + } socket_close; + + message { + uint16 connection_id; + uint8 data[] @end; + } socket_data; + + message { + uint16 connection_id; + } socket_closed_ack; + + message { + uint16 connection_id; + uint32 num_tokens; + } @ctype(SpiceMsgTunnelSocketTokens) socket_token; + + client: + message { + tunnel_service_type type; + uint32 id; + uint32 group; + uint32 port; + uint8 *name[cstring()] @nocopy; + uint8 *description[cstring()] @nocopy; + switch (type) { + case IPP: + TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo); + } u; + } @ctype(SpiceMsgcTunnelAddGenericService) service_add = 101; + + message { + uint32 id; + } @ctype(SpiceMsgcTunnelRemoveService) service_remove; + + message { + uint16 connection_id; + uint32 tokens; + } socket_open_ack; + + message { + uint16 connection_id; + } socket_open_nack; + + message { + uint16 connection_id; + } socket_fin; + + message { + uint16 connection_id; + } socket_closed; + + message { + uint16 connection_id; + } socket_closed_ack; + + message { + uint16 connection_id; + uint8 data[] @end; + } socket_data; + + message { + uint16 connection_id; + uint32 num_tokens; + } @ctype(SpiceMsgcTunnelSocketTokens) socket_token; +}; + +enum32 vsc_message_type { + Init = 1, + Error, + ReaderAdd, + ReaderRemove, + ATR, + CardRemove, + APDU, + Flush, + FlushComplete +}; + +struct VscMessageHeader { + vsc_message_type type; + uint32 reader_id; + uint32 length; +} @ctype(VSCMsgHeader); + +struct VscMessageError { + uint32 code; +} @ctype(VSCMsgError); + +struct VscMessageAPDU { + uint8 data[]; +} @ctype(VSCMsgAPDU); + +struct VscMessageATR { + uint8 data[]; +} @ctype(VSCMsgATR); + +struct VscMessageReaderAdd { + int8 *reader_name[] @zero_terminated @nonnull @end @nomarshal; +} @ctype(VSCMsgReaderAdd); + +channel SmartcardChannel : BaseChannel { + server: + message { + vsc_message_type type; + uint32 reader_id; + uint32 length; + uint8 data[length] @end @nomarshal; + } @ctype(SpiceMsgSmartcard) data = 101; + + client: + message { + VscMessageHeader header; + switch (header.type) { + case ReaderAdd: + VscMessageReaderAdd add; + case ATR: + case APDU: + VscMessageATR atr_data; + case Error: + VscMessageError error; + } u @anon; + } @ctype(SpiceMsgcSmartcard) data = 101; + + message { + vsc_message_type type; + uint32 reader_id; + uint32 length; + } @ctype(VSCMsgHeader) header = 101; + + message { + uint32 code; + } @ctype(VSCMsgError) error = 101; + + message { + uint8 data[]; + } @ctype(VSCMsgATR) atr = 101; + + message { + int8 reader_name[] @zero_terminated @nonnull; + } @ctype(VSCMsgReaderAdd) reader_add = 101; +} @ifdef(USE_SMARTCARD); + +channel SpicevmcChannel : BaseChannel { +server: + Data data = 101; +client: + Data data = 101; +}; + +channel UsbredirChannel : SpicevmcChannel { +}; + +channel PortChannel : SpicevmcChannel { + client: + message { + uint8 event; + } event = 201; + server: + message { + uint32 name_size; + uint8 *name[name_size] @zero_terminated @marshall @nonnull; + uint8 opened; + } init = 201; + message { + uint8 event; + } event; +}; + +channel WebDAVChannel : PortChannel { +}; + +protocol Spice { + MainChannel main = 1; + DisplayChannel display; + InputsChannel inputs; + CursorChannel cursor; + PlaybackChannel playback; + RecordChannel record; + TunnelChannel tunnel; + SmartcardChannel smartcard; + UsbredirChannel usbredir; + PortChannel port; + WebDAVChannel webdav; +}; diff --git a/spice-common/spice1.proto b/spice-common/spice1.proto new file mode 100644 index 0000000..6adf312 --- /dev/null +++ b/spice-common/spice1.proto @@ -0,0 +1,943 @@ +/* built in types: + int8, uint8, 16, 32, 64 +*/ + +typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); + +struct Point { + int32 x; + int32 y; +}; + +struct Point16 { + int16 x; + int16 y; +}; + +struct PointFix { + fixed28_4 x; + fixed28_4 y; +}; + +struct Rect { + int32 top; + int32 left; + int32 bottom; + int32 right; +}; + +enum32 link_err { + OK, + ERROR, + INVALID_MAGIC, + INVALID_DATA, + VERSION_MISMATCH, + NEED_SECURED, + NEED_UNSECURED, + PERMISSION_DENIED, + BAD_CONNECTION_ID, + CHANNEL_NOT_AVAILABLE +}; + +enum32 warn_code { + WARN_GENERAL +} @prefix(SPICE_); + +enum32 info_code { + INFO_GENERAL +} @prefix(SPICE_); + +flags32 migrate_flags { + NEED_FLUSH, + NEED_DATA_TRANSFER +} @prefix(SPICE_MIGRATE_); + +enum32 notify_severity { + INFO, + WARN, + ERROR, +}; + +enum32 notify_visibility { + LOW, + MEDIUM, + HIGH, +}; + +flags32 mouse_mode { + SERVER, + CLIENT, +}; + +enum16 pubkey_type { + INVALID, + RSA, + RSA2, + DSA, + DSA1, + DSA2, + DSA3, + DSA4, + DH, + EC, +}; + +message Empty { +}; + +message Data { + uint8 data[] @end @ctype(uint8_t); +} @nocopy; + +struct ChannelWait { + uint8 channel_type; + uint8 channel_id; + uint64 message_serial; +} @ctype(SpiceWaitForChannel); + +channel BaseChannel { + server: + message { + migrate_flags flags; + } migrate; + + Data migrate_data; + + message { + uint32 generation; + uint32 window; + } set_ack; + + message { + uint32 id; + uint64 timestamp; + uint8 data[] @ctype(uint8_t) @as_ptr(data_len); + } ping; + + message { + uint8 wait_count; + ChannelWait wait_list[wait_count] @end; + } wait_for_channels; + + message { + uint64 time_stamp; + link_err reason; + } @ctype(SpiceMsgDisconnect) disconnecting; + + message { + uint64 time_stamp; + notify_severity severity; + notify_visibility visibilty; + uint32 what; /* error_code/warn_code/info_code */ + uint32 message_len; + uint8 message[message_len] @end @nomarshal; + uint8 zero @end @ctype(uint8_t) @nomarshal; + } notify; + + client: + message { + uint32 generation; + } ack_sync; + + Empty ack; + + message { + uint32 id; + uint64 timestamp; + } @ctype(SpiceMsgPing) pong; + + Empty migrate_flush_mark; + + Data migrate_data; + + message { + uint64 time_stamp; + link_err reason; + } @ctype(SpiceMsgDisconnect) disconnecting; +}; + +struct ChannelId { + uint8 type; + uint8 id; +}; + +struct DstInfo { + uint16 port; + uint16 sport; + uint32 host_offset @zero; + uint32 host_size; + pubkey_type pub_key_type @minor(1); + uint32 pub_key_offset @minor(1) @zero; + uint32 pub_key_size @minor(1); + uint8 host_data[host_size] @as_ptr @zero_terminated; + uint8 pub_key_data[pub_key_size] @minor(1) @as_ptr @zero_terminated; +} @ctype(SpiceMigrationDstInfo); + +channel MainChannel : BaseChannel { + server: + message { + DstInfo dst_info; + } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101; + + Empty migrate_cancel; + + message { + uint32 session_id; + uint32 display_channels_hint; + uint32 supported_mouse_modes; + uint32 current_mouse_mode; + uint32 agent_connected; + uint32 agent_tokens; + uint32 multi_media_time; + uint32 ram_hint; + } init; + + message { + uint32 num_of_channels; + ChannelId channels[num_of_channels] @end; + } @ctype(SpiceMsgChannels) channels_list; + + message { + mouse_mode supported_modes; + mouse_mode current_mode @unique_flag; + } mouse_mode; + + message { + uint32 time; + } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time; + + Empty agent_connected; + + message { + link_err error_code; + } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected; + + Data agent_data; + + message { + uint32 num_tokens; + } @ctype(SpiceMsgMainAgentTokens) agent_token; + + message { + uint16 port; + uint16 sport; + uint32 host_offset @zero; + uint32 host_size; + uint32 cert_subject_offset @zero; + uint32 cert_subject_size; + uint8 host_data[host_size] @as_ptr @zero_terminated; + uint8 cert_subject_data[cert_subject_size] @as_ptr @zero_terminated; + } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host; + + client: + message { + uint64 cache_size; + } @ctype(SpiceMsgcClientInfo) client_info = 101; + + Empty migrate_connected; + + Empty migrate_connect_error; + + Empty attach_channels; + + message { + mouse_mode mode; + } mouse_mode_request; + + message { + uint32 num_tokens; + } agent_start; + + Data agent_data; + + message { + uint32 num_tokens; + } @ctype(SpiceMsgcMainAgentTokens) agent_token; +}; + +enum32 clip_type { + NONE, + RECTS +}; + +flags32 path_flags { /* TODO: C enum names changes */ + BEGIN = 0, + END = 1, + CLOSE = 3, + BEZIER = 4, +} @prefix(SPICE_PATH_); + +enum32 video_codec_type { + MJPEG = 1, +}; + +flags32 stream_flags { + TOP_DOWN = 0, +}; + +enum32 brush_type { + NONE, + SOLID, + PATTERN, +}; + +flags8 mask_flags { + INVERS, +}; + +enum8 image_type { + BITMAP, + QUIC, + RESERVED, + LZ_PLT = 100, + LZ_RGB, + GLZ_RGB, + FROM_CACHE, +}; + +flags8 image_flags { + CACHE_ME, +}; + +enum8 bitmap_fmt { + INVALID, + 1BIT_LE, + 1BIT_BE, + 4BIT_LE, + 4BIT_BE, + 8BIT /* 8bit indexed mode */, + 16BIT, /* 0555 mode */ + 24BIT /* 3 byte, brg */, + 32BIT /* 4 byte, xrgb in little endian format */, + RGBA /* 4 byte, argb in little endian format */ +}; + +flags8 bitmap_flags { + PAL_CACHE_ME, + PAL_FROM_CACHE, + TOP_DOWN, +}; + +enum8 image_scale_mode { + INTERPOLATE, + NEAREST, +}; + +flags16 ropd { + INVERS_SRC, + INVERS_BRUSH, + INVERS_DEST, + OP_PUT, + OP_OR, + OP_AND, + OP_XOR, + OP_BLACKNESS, + OP_WHITENESS, + OP_INVERS, + INVERS_RES, +}; + +flags8 line_flags { + STYLED = 3, + START_WITH_GAP = 2, +}; + +enum8 line_cap { + ROUND, + SQUARE, + BUTT, +}; + +enum8 line_join { + ROUND, + BEVEL, + MITER, +}; + +flags16 string_flags { + RASTER_A1, + RASTER_A4, + RASTER_A8, + RASTER_TOP_DOWN, +}; + +enum8 resource_type { + INVALID, + PIXMAP +} @prefix(SPICE_RES_TYPE_); + +struct ClipRects { + uint32 num_rects; + Rect rects[num_rects] @end; +}; + +struct PathSegment { + path_flags flags; + uint32 count; + PointFix points[count] @end; +} @ctype(SpicePathSeg); + +struct Path { + uint32 segments_size @bytes_count(num_segments); + PathSegment segments[bytes(segments_size, num_segments)] @ptr_array; +}; + +struct Clip { + clip_type type; + switch (type) { + case RECTS: + ClipRects *rects @outvar(cliprects); + default: + uint64 data @zero; + } u @anon; +}; + +struct DisplayBase { + uint32 surface_id @virtual(0); + Rect box; + Clip clip; +} @ctype(SpiceMsgDisplayBase); + +struct ResourceID { + uint8 type; + uint64 id; +}; + +struct WaitForChannel { + uint8 channel_type; + uint8 channel_id; + uint64 message_serial; +}; + +struct Palette { + uint64 unique; + uint16 num_ents; + uint32 ents[num_ents] @end; +}; + +struct BitmapData { + bitmap_fmt format; + bitmap_flags flags; + uint32 x; + uint32 y; + uint32 stride; + switch (flags) { + case PAL_FROM_CACHE: + uint64 palette_id; + default: + Palette *palette @outvar(bitmap); + } pal @anon; + uint8 *data[image_size(8, stride, y)] @chunk; /* pointer to array, not array of pointers as in C */ +} @ctype(SpiceBitmap); + +struct BinaryData { + uint32 data_size; + uint8 data[data_size] @nomarshal @chunk; +} @ctype(SpiceQUICData); + +struct LZPLTData { + bitmap_flags flags; + uint32 data_size; + switch (flags) { + case PAL_FROM_CACHE: + uint64 palette_id; + default: + Palette *palette @nonnull @outvar(lzplt); + } pal @anon; + uint8 data[data_size] @nomarshal @chunk; +}; + +struct Image { + struct ImageDescriptor { + uint64 id; + image_type type; + image_flags flags; + uint32 width; + uint32 height; + } descriptor; + + switch (descriptor.type) { + case BITMAP: + BitmapData bitmap; + case QUIC: + BinaryData quic; + case LZ_RGB: + case GLZ_RGB: + BinaryData lz_rgb; + case LZ_PLT: + LZPLTData lz_plt; + } u; +}; + +struct Pattern { + Image *pat @nonnull; + Point pos; +}; + +struct Brush { + brush_type type; + switch (type) { + case SOLID: + uint32 color; + case PATTERN: + Pattern pattern; + } u @fixedsize; +}; + +struct QMask { + mask_flags flags; + Point pos; + Image *bitmap; +}; + +struct LineAttr { + line_flags flags; + line_join join_style @zero; + line_cap end_style @zero; + uint8 style_nseg; + fixed28_4 width @zero; + fixed28_4 miter_limit @zero; + fixed28_4 *style[style_nseg]; +}; + +struct RasterGlyphA1 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(1, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct RasterGlyphA4 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(4, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct RasterGlyphA8 { + Point render_pos; + Point glyph_origin; + uint16 width; + uint16 height; + uint8 data[image_size(8, width, height)] @end; +} @ctype(SpiceRasterGlyph); + +struct String { + uint16 length; + string_flags flags; /* Special: Only one of a1/a4/a8 set */ + switch (flags) { + case RASTER_A1: + RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + case RASTER_A4: + RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + case RASTER_A8: + RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; + } u @anon; +}; + +struct StreamDataHeader { + uint32 id; + uint32 multi_media_time; +}; + +channel DisplayChannel : BaseChannel { + server: + message { + uint32 x_res; + uint32 y_res; + uint32 bits; + } mode = 101; + + Empty mark; + Empty reset; + + message { + DisplayBase base; + Point src_pos; + } copy_bits; + + message { + uint16 count; + ResourceID resources[count] @end; + } @ctype(SpiceResourceList) inval_list; + + message { + uint8 wait_count; + WaitForChannel wait_list[wait_count] @end; + } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps; + + message { + uint64 id; + } @ctype(SpiceMsgDisplayInvalOne) inval_palette; + + Empty inval_all_palettes; + + message { + uint32 surface_id @virtual(0); + uint32 id; + stream_flags flags; + video_codec_type codec_type; + uint64 stamp; + uint32 stream_width; + uint32 stream_height; + uint32 src_width; + uint32 src_height; + Rect dest; + Clip clip; + } stream_create = 122; + + message { + StreamDataHeader base; + uint32 data_size; + uint32 pad_size @zero; + uint8 data[data_size] @end @nomarshal; + /* Ignore: uint8 padding[pad_size] */ + } stream_data; + + message { + uint32 id; + Clip clip; + } stream_clip; + + message { + uint32 id; + } stream_destroy; + + Empty stream_destroy_all; + + message { + DisplayBase base; + struct Fill { + Brush brush @outvar(brush); + uint16 rop_descriptor; + QMask mask @outvar(mask); + } data; + } draw_fill = 302; + + message { + DisplayBase base; + struct Opaque { + Image *src_bitmap; + Rect src_area; + Brush brush; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_opaque; + + message { + DisplayBase base; + struct Copy { + Image *src_bitmap; + Rect src_area; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_copy; + + message { + DisplayBase base; + struct Blend { + Image *src_bitmap; + Rect src_area; + ropd rop_descriptor; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } @ctype(SpiceCopy) data; + } draw_blend; + + message { + DisplayBase base; + struct Blackness { + QMask mask @outvar(mask); + } data; + } draw_blackness; + + message { + DisplayBase base; + struct Whiteness { + QMask mask @outvar(mask); + } data; + } draw_whiteness; + + message { + DisplayBase base; + struct Invers { + QMask mask @outvar(mask); + } data; + } draw_invers; + + message { + DisplayBase base; + struct Rop3 { + Image *src_bitmap; + Rect src_area; + Brush brush; + uint8 rop3; + image_scale_mode scale_mode; + QMask mask @outvar(mask); + } data; + } draw_rop3; + + message { + DisplayBase base; + struct Stroke { + Path *path; + LineAttr attr; + Brush brush; + uint16 fore_mode; + uint16 back_mode; + } data; + } draw_stroke; + + message { + DisplayBase base; + struct Text { + String *str; + Rect back_area; + Brush fore_brush @outvar(fore_brush); + Brush back_brush @outvar(back_brush); + uint16 fore_mode; + uint16 back_mode; + } data; + } draw_text; + + message { + DisplayBase base; + struct Transparent { + Image *src_bitmap; + Rect src_area; + uint32 src_color; + uint32 true_color; + } data; + } draw_transparent; + + message { + DisplayBase base; + struct AlphaBlend { + int8 alpha_flags @virtual(0); + uint8 alpha; + Image *src_bitmap; + Rect src_area; + } data; + } draw_alpha_blend; + + client: + message { + uint8 pixmap_cache_id; + int64 pixmap_cache_size; //in pixels + uint8 glz_dictionary_id; + int32 glz_dictionary_window_size; // in pixels + } init = 101; +}; + +flags32 keyboard_modifier_flags { + SCROLL_LOCK, + NUM_LOCK, + CAPS_LOCK +}; + +enum32 mouse_button { + INVALID, + LEFT, + MIDDLE, + RIGHT, + UP, + DOWN, +}; + +flags32 mouse_button_mask { + LEFT, + MIDDLE, + RIGHT +}; + +channel InputsChannel : BaseChannel { + client: + message { + uint32 code; + } @ctype(SpiceMsgcKeyDown) key_down = 101; + + message { + uint32 code; + } @ctype(SpiceMsgcKeyUp) key_up; + + message { + keyboard_modifier_flags modifiers; + } @ctype(SpiceMsgcKeyModifiers) key_modifiers; + + message { + int32 dx; + int32 dy; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111; + + message { + uint32 x; + uint32 y; + mouse_button_mask buttons_state; + uint8 display_id; + } @ctype(SpiceMsgcMousePosition) mouse_position; + + message { + mouse_button button; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMousePress) mouse_press; + + message { + mouse_button button; + mouse_button_mask buttons_state; + } @ctype(SpiceMsgcMouseRelease) mouse_release; + + server: + message { + keyboard_modifier_flags keyboard_modifiers; + } init = 101; + + message { + keyboard_modifier_flags modifiers; + } key_modifiers; + + Empty mouse_motion_ack = 111; +}; + +enum16 cursor_type { + ALPHA, + MONO, + COLOR4, + COLOR8, + COLOR16, + COLOR24, + COLOR32, +}; + +flags32 cursor_flags { + NONE, /* Means no cursor */ + CACHE_ME, + FROM_CACHE, +}; + +struct CursorHeader { + uint64 unique; + cursor_type type; + uint16 width; + uint16 height; + uint16 hot_spot_x; + uint16 hot_spot_y; +}; + +struct Cursor { + cursor_flags flags; + CursorHeader header; + uint8 data[] @as_ptr(data_size); +}; + +channel CursorChannel : BaseChannel { + server: + message { + Point16 position; + uint16 trail_length; + uint16 trail_frequency; + uint8 visible; + Cursor cursor; + } init = 101; + + Empty reset; + + message { + Point16 position; + uint8 visible; + Cursor cursor; + } set; + + message { + Point16 position; + } move; + + Empty hide; + + message { + uint16 length; + uint16 frequency; + } trail; + + message { + uint64 id; + } @ctype(SpiceMsgDisplayInvalOne) inval_one; + + Empty inval_all; +}; + +enum32 audio_data_mode { + INVALID, + RAW, + CELT_0_5_1, + OPUS, +}; + +enum32 audio_fmt { + INVALID, + S16, +}; + +channel PlaybackChannel : BaseChannel { + server: + message { + uint32 time; + uint8 data[] @as_ptr(data_size); + } @ctype(SpiceMsgPlaybackPacket) data = 101; + + message { + uint32 time; + audio_data_mode mode; + uint8 data[] @as_ptr(data_size); + } mode; + + message { + uint32 channels; + audio_fmt format; + uint32 frequency; + uint32 time; + } start; + + Empty stop; +}; + +channel RecordChannel : BaseChannel { + server: + message { + uint32 channels; + audio_fmt format; + uint32 frequency; + } start = 101; + + Empty stop; + client: + message { + uint32 time; + uint8 data[] @nomarshal @as_ptr(data_size); + } @ctype(SpiceMsgcRecordPacket) data = 101; + + message { + uint32 time; + audio_data_mode mode; + uint8 data[] @as_ptr(data_size); + } mode; + + message { + uint32 time; + } start_mark; +}; + +protocol Spice { + MainChannel main = 1; + DisplayChannel display; + InputsChannel inputs; + CursorChannel cursor; + PlaybackChannel playback; + RecordChannel record; +}; diff --git a/spice-common/spice_codegen.py b/spice-common/spice_codegen.py new file mode 100755 index 0000000..569cccc --- /dev/null +++ b/spice-common/spice_codegen.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python + +import os +import sys +from optparse import OptionParser +import traceback +from python_modules import spice_parser +from python_modules import ptypes +from python_modules import codegen +from python_modules import demarshal +from python_modules import marshal +import six + +def write_channel_enums(writer, channel, client, describe): + messages = list(filter(lambda m : m.channel == channel, \ + channel.client_messages if client else channel.server_messages)) + if len(messages) == 0: + return + if client: + prefix = [ "MSGC" ] + else: + prefix = [ "MSG" ] + if channel.member_name: + prefix.append(channel.member_name.upper()) + if not describe: + writer.begin_block("enum") + else: + writer.begin_block("static const value_string %s_vs[] = " % (codegen.prefix_underscore_lower(*[x.lower() for x in prefix]))) + i = 0 + prefix.append(None) # To be replaced with name + for m in messages: + prefix[-1] = m.name.upper() + enum = codegen.prefix_underscore_upper(*prefix) + if describe: + writer.writeln("{ %s, \"%s %s\" }," % (enum, "Client" if client else "Server", m.name.upper())) + else: + if m.value == i: + writer.writeln("%s," % enum) + i = i + 1 + else: + writer.writeln("%s = %s," % (enum, m.value)) + i = m.value + 1 + if describe: + writer.writeln("{ 0, NULL }"); + else: + if channel.member_name: + prefix[-1] = prefix[-2] + prefix[-2] = "END" + writer.newline() + writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix))) + writer.end_block(semicolon=True) + writer.newline() + +def write_channel_type_enum(writer, describe=False): + i = 0 + if describe: + writer.begin_block("static const value_string channel_types_vs[] =") + else: + writer.begin_block("enum") + for c in proto.channels: + enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper()) + if describe: + writer.writeln("{ %s, \"%s\" }," % (enum, c.name.upper())) + else: + if c.value == i: + writer.writeln("%s," % enum) + i = i + 1 + else: + writer.writeln("%s = %s," % (enum, c.value)) + i = c.value + 1 + writer.newline() + if describe: + writer.writeln("{ 0, NULL }") + else: + writer.writeln("SPICE_END_CHANNEL") + writer.end_block(semicolon=True) + writer.newline() + + +def write_enums(writer, describe=False): + writer.writeln("#ifndef _H_SPICE_ENUMS") + writer.writeln("#define _H_SPICE_ENUMS") + writer.newline() + + # Define enums + for t in ptypes.get_named_types(): + if isinstance(t, ptypes.EnumBaseType): + t.c_define(writer) + if describe: + t.c_describe(writer) + + write_channel_type_enum(writer) + if (describe): + write_channel_type_enum(writer, True) + + for c in ptypes.get_named_types(): + if not isinstance(c, ptypes.ChannelType): + continue + write_channel_enums(writer, c, False, False) + if describe: + write_channel_enums(writer, c, False, describe) + write_channel_enums(writer, c, True, False) + if describe: + write_channel_enums(writer, c, True, describe) + + writer.writeln("#endif /* _H_SPICE_ENUMS */") + +parser = OptionParser(usage="usage: %prog [options] ") +parser.add_option("-e", "--generate-enums", + action="store_true", dest="generate_enums", default=False, + help="Generate enums") +parser.add_option("-w", "--generate-wireshark-dissector", + action="store_true", dest="generate_dissector", default=False, + help="Generate Wireshark dissector definitions") +parser.add_option("-d", "--generate-demarshallers", + action="store_true", dest="generate_demarshallers", default=False, + help="Generate demarshallers") +parser.add_option("-m", "--generate-marshallers", + action="store_true", dest="generate_marshallers", default=False, + help="Generate message marshallers") +parser.add_option("-P", "--private-marshallers", + action="store_true", dest="private_marshallers", default=False, + help="Generate private message marshallers") +parser.add_option("-M", "--generate-struct-marshaller", + action="append", dest="struct_marshallers", + help="Generate struct marshallers") +parser.add_option("-a", "--assert-on-error", + action="store_true", dest="assert_on_error", default=False, + help="Assert on error") +parser.add_option("-H", "--header", + action="store_true", dest="header", default=False, + help="Generate header") +parser.add_option("-p", "--print-error", + action="store_true", dest="print_error", default=False, + help="Print errors") +parser.add_option("-s", "--server", + action="store_true", dest="server", default=False, + help="Print errors") +parser.add_option("-c", "--client", + action="store_true", dest="client", default=False, + help="Print errors") +parser.add_option("-k", "--keep-identical-file", + action="store_true", dest="keep_identical_file", default=False, + help="Print errors") +parser.add_option("-i", "--include", + action="append", dest="includes", metavar="FILE", + help="Include FILE in generated code") +parser.add_option("--prefix", dest="prefix", + help="set public symbol prefix", default="") +parser.add_option("--ptrsize", dest="ptrsize", + help="set default pointer size", default="4") + +(options, args) = parser.parse_args() + +if len(args) == 0: + parser.error("No protocol file specified") + +if len(args) == 1: + parser.error("No destination file specified") + +ptypes.default_pointer_size = int(options.ptrsize) + +proto_file = args[0] +dest_file = args[1] +proto = spice_parser.parse(proto_file) + +if proto == None: + exit(1) + +codegen.set_prefix(proto.name) +writer = codegen.CodeWriter() +writer.header = codegen.CodeWriter() +writer.set_option("source", os.path.basename(proto_file)) + +license = """/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +""" + +writer.public_prefix = options.prefix + +writer.writeln("/* this is a file autogenerated by spice_codegen.py */") +writer.write(license) +writer.header.writeln("/* this is a file autogenerated by spice_codegen.py */") +writer.header.write(license) +if not options.header and not options.generate_enums: + writer.writeln("#ifdef HAVE_CONFIG_H") + writer.writeln("#include ") + writer.writeln("#endif") + +if options.assert_on_error: + writer.set_option("assert_on_error") + +if options.print_error: + writer.set_option("print_error") + +if options.includes: + for i in options.includes: + writer.header.writeln('#include <%s>' % i) + writer.writeln('#include <%s>' % i) + +if options.generate_enums or options.generate_dissector: + write_enums(writer, options.generate_dissector) + +if options.generate_demarshallers: + if not options.server and not options.client: + print >> sys.stderr, "Must specify client and/or server" + sys.exit(1) + demarshal.write_includes(writer) + + if options.server: + demarshal.write_protocol_parser(writer, proto, False) + if options.client: + demarshal.write_protocol_parser(writer, proto, True) + +if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0): + marshal.write_includes(writer) + +if options.generate_marshallers: + if not options.server and not options.client: + print >> sys.stderr, "Must specify client and/or server" + sys.exit(1) + if options.server: + marshal.write_protocol_marshaller(writer, proto, False, options.private_marshallers) + if options.client: + marshal.write_protocol_marshaller(writer, proto, True, options.private_marshallers) + +if options.struct_marshallers: + for structname in options.struct_marshallers: + t = ptypes.lookup_type(structname) + marshal.write_marshal_ptr_function(writer, t, False) + +if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0): + marshal.write_trailer(writer) + +if options.header: + content = writer.header.getvalue() +else: + content = writer.getvalue() +if options.keep_identical_file: + try: + f = open(dest_file, 'rb') + old_content = f.read() + f.close() + + if content == old_content: + six.print_("No changes to %s" % dest_file) + sys.exit(0) + + except IOError: + pass + +f = open(dest_file, 'wb') +if six.PY3: + f.write(bytes(content, 'UTF-8')) +else: + f.write(content) +f.close() + +six.print_("Wrote %s" % dest_file) +sys.exit(0) diff --git a/spice-common/tests/Makefile.am b/spice-common/tests/Makefile.am new file mode 100644 index 0000000..10033c0 --- /dev/null +++ b/spice-common/tests/Makefile.am @@ -0,0 +1,66 @@ +NULL = + +TESTS = test_logging test_marshallers +noinst_PROGRAMS = $(TESTS) + +test_logging_SOURCES = test-logging.c +test_logging_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB2_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) +test_logging_LDADD = \ + $(top_builddir)/common/libspice-common.la \ + $(GLIB2_LIBS) \ + $(GIO_UNIX_LIBS) \ + $(NULL) + + +test_marshallers_SOURCES = \ + generated_test_marshallers.c \ + generated_test_marshallers.h \ + test-marshallers.c \ + test-marshallers.h \ + $(NULL) +test_marshallers_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB2_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) +test_marshallers_LDADD = \ + $(top_builddir)/common/libspice-common.la \ + $(GLIB2_LIBS) \ + $(NULL) + +# Avoid need for python(pyparsing) by end users +TEST_MARSHALLERS = \ + generated_test_marshallers.c \ + generated_test_marshallers.h \ + $(NULL) + +BUILT_SOURCES = $(TEST_MARSHALLERS) + +MARSHALLERS_DEPS = \ + $(top_srcdir)/python_modules/__init__.py \ + $(top_srcdir)/python_modules/codegen.py \ + $(top_srcdir)/python_modules/demarshal.py \ + $(top_srcdir)/python_modules/marshal.py \ + $(top_srcdir)/python_modules/ptypes.py \ + $(top_srcdir)/python_modules/spice_parser.py \ + $(top_srcdir)/spice_codegen.py \ + $(NULL) + +# Note despite being autogenerated these are not part of CLEANFILES, they are +# actually a part of EXTRA_DIST, to avoid the need for pyparser by end users +generated_test_marshallers.c: $(srcdir)/test-marshallers.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers --server --include test-marshallers.h $< $@ >/dev/null +generated_test_marshallers.h: $(srcdir)/test-marshallers.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers --server --include test-marshallers.h -H $< $@ >/dev/null + +EXTRA_DIST = \ + $(TEST_MARSHALLERS) \ + test-marshallers.proto \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/spice-common/tests/Makefile.in b/spice-common/tests/Makefile.in new file mode 100644 index 0000000..bc0efa2 --- /dev/null +++ b/spice-common/tests/Makefile.in @@ -0,0 +1,1127 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = test_logging$(EXEEXT) test_marshallers$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = test_logging$(EXEEXT) test_marshallers$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_test_logging_OBJECTS = test_logging-test-logging.$(OBJEXT) +test_logging_OBJECTS = $(am_test_logging_OBJECTS) +am__DEPENDENCIES_1 = +test_logging_DEPENDENCIES = $(top_builddir)/common/libspice-common.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_logging_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_logging_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am__objects_1 = +am_test_marshallers_OBJECTS = \ + test_marshallers-generated_test_marshallers.$(OBJEXT) \ + test_marshallers-test-marshallers.$(OBJEXT) $(am__objects_1) +test_marshallers_OBJECTS = $(am_test_marshallers_OBJECTS) +test_marshallers_DEPENDENCIES = \ + $(top_builddir)/common/libspice-common.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_marshallers_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(test_marshallers_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_logging_SOURCES) $(test_marshallers_SOURCES) +DIST_SOURCES = $(test_logging_SOURCES) $(test_marshallers_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CELT051_CFLAGS = @CELT051_CFLAGS@ +CELT051_LIBS = @CELT051_LIBS@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPUS_CFLAGS = @OPUS_CFLAGS@ +OPUS_LIBS = @OPUS_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOCOL_CFLAGS = @PROTOCOL_CFLAGS@ +PROTOCOL_LIBS = @PROTOCOL_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_COMMON_CFLAGS = @SPICE_COMMON_CFLAGS@ +SPICE_COMMON_LIBS = @SPICE_COMMON_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +test_logging_SOURCES = test-logging.c +test_logging_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB2_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) + +test_logging_LDADD = \ + $(top_builddir)/common/libspice-common.la \ + $(GLIB2_LIBS) \ + $(GIO_UNIX_LIBS) \ + $(NULL) + +test_marshallers_SOURCES = \ + generated_test_marshallers.c \ + generated_test_marshallers.h \ + test-marshallers.c \ + test-marshallers.h \ + $(NULL) + +test_marshallers_CFLAGS = \ + -I$(top_srcdir) \ + $(GLIB2_CFLAGS) \ + $(PROTOCOL_CFLAGS) \ + $(NULL) + +test_marshallers_LDADD = \ + $(top_builddir)/common/libspice-common.la \ + $(GLIB2_LIBS) \ + $(NULL) + + +# Avoid need for python(pyparsing) by end users +TEST_MARSHALLERS = \ + generated_test_marshallers.c \ + generated_test_marshallers.h \ + $(NULL) + +BUILT_SOURCES = $(TEST_MARSHALLERS) +MARSHALLERS_DEPS = \ + $(top_srcdir)/python_modules/__init__.py \ + $(top_srcdir)/python_modules/codegen.py \ + $(top_srcdir)/python_modules/demarshal.py \ + $(top_srcdir)/python_modules/marshal.py \ + $(top_srcdir)/python_modules/ptypes.py \ + $(top_srcdir)/python_modules/spice_parser.py \ + $(top_srcdir)/spice_codegen.py \ + $(NULL) + +EXTRA_DIST = \ + $(TEST_MARSHALLERS) \ + test-marshallers.proto \ + $(NULL) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test_logging$(EXEEXT): $(test_logging_OBJECTS) $(test_logging_DEPENDENCIES) $(EXTRA_test_logging_DEPENDENCIES) + @rm -f test_logging$(EXEEXT) + $(AM_V_CCLD)$(test_logging_LINK) $(test_logging_OBJECTS) $(test_logging_LDADD) $(LIBS) + +test_marshallers$(EXEEXT): $(test_marshallers_OBJECTS) $(test_marshallers_DEPENDENCIES) $(EXTRA_test_marshallers_DEPENDENCIES) + @rm -f test_marshallers$(EXEEXT) + $(AM_V_CCLD)$(test_marshallers_LINK) $(test_marshallers_OBJECTS) $(test_marshallers_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_logging-test-logging.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_marshallers-generated_test_marshallers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_marshallers-test-marshallers.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_logging-test-logging.o: test-logging.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_logging_CFLAGS) $(CFLAGS) -MT test_logging-test-logging.o -MD -MP -MF $(DEPDIR)/test_logging-test-logging.Tpo -c -o test_logging-test-logging.o `test -f 'test-logging.c' || echo '$(srcdir)/'`test-logging.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_logging-test-logging.Tpo $(DEPDIR)/test_logging-test-logging.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-logging.c' object='test_logging-test-logging.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_logging_CFLAGS) $(CFLAGS) -c -o test_logging-test-logging.o `test -f 'test-logging.c' || echo '$(srcdir)/'`test-logging.c + +test_logging-test-logging.obj: test-logging.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_logging_CFLAGS) $(CFLAGS) -MT test_logging-test-logging.obj -MD -MP -MF $(DEPDIR)/test_logging-test-logging.Tpo -c -o test_logging-test-logging.obj `if test -f 'test-logging.c'; then $(CYGPATH_W) 'test-logging.c'; else $(CYGPATH_W) '$(srcdir)/test-logging.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_logging-test-logging.Tpo $(DEPDIR)/test_logging-test-logging.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-logging.c' object='test_logging-test-logging.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_logging_CFLAGS) $(CFLAGS) -c -o test_logging-test-logging.obj `if test -f 'test-logging.c'; then $(CYGPATH_W) 'test-logging.c'; else $(CYGPATH_W) '$(srcdir)/test-logging.c'; fi` + +test_marshallers-generated_test_marshallers.o: generated_test_marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -MT test_marshallers-generated_test_marshallers.o -MD -MP -MF $(DEPDIR)/test_marshallers-generated_test_marshallers.Tpo -c -o test_marshallers-generated_test_marshallers.o `test -f 'generated_test_marshallers.c' || echo '$(srcdir)/'`generated_test_marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshallers-generated_test_marshallers.Tpo $(DEPDIR)/test_marshallers-generated_test_marshallers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='generated_test_marshallers.c' object='test_marshallers-generated_test_marshallers.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -c -o test_marshallers-generated_test_marshallers.o `test -f 'generated_test_marshallers.c' || echo '$(srcdir)/'`generated_test_marshallers.c + +test_marshallers-generated_test_marshallers.obj: generated_test_marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -MT test_marshallers-generated_test_marshallers.obj -MD -MP -MF $(DEPDIR)/test_marshallers-generated_test_marshallers.Tpo -c -o test_marshallers-generated_test_marshallers.obj `if test -f 'generated_test_marshallers.c'; then $(CYGPATH_W) 'generated_test_marshallers.c'; else $(CYGPATH_W) '$(srcdir)/generated_test_marshallers.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshallers-generated_test_marshallers.Tpo $(DEPDIR)/test_marshallers-generated_test_marshallers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='generated_test_marshallers.c' object='test_marshallers-generated_test_marshallers.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -c -o test_marshallers-generated_test_marshallers.obj `if test -f 'generated_test_marshallers.c'; then $(CYGPATH_W) 'generated_test_marshallers.c'; else $(CYGPATH_W) '$(srcdir)/generated_test_marshallers.c'; fi` + +test_marshallers-test-marshallers.o: test-marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -MT test_marshallers-test-marshallers.o -MD -MP -MF $(DEPDIR)/test_marshallers-test-marshallers.Tpo -c -o test_marshallers-test-marshallers.o `test -f 'test-marshallers.c' || echo '$(srcdir)/'`test-marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshallers-test-marshallers.Tpo $(DEPDIR)/test_marshallers-test-marshallers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-marshallers.c' object='test_marshallers-test-marshallers.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -c -o test_marshallers-test-marshallers.o `test -f 'test-marshallers.c' || echo '$(srcdir)/'`test-marshallers.c + +test_marshallers-test-marshallers.obj: test-marshallers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -MT test_marshallers-test-marshallers.obj -MD -MP -MF $(DEPDIR)/test_marshallers-test-marshallers.Tpo -c -o test_marshallers-test-marshallers.obj `if test -f 'test-marshallers.c'; then $(CYGPATH_W) 'test-marshallers.c'; else $(CYGPATH_W) '$(srcdir)/test-marshallers.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshallers-test-marshallers.Tpo $(DEPDIR)/test_marshallers-test-marshallers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-marshallers.c' object='test_marshallers-test-marshallers.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_marshallers_CFLAGS) $(CFLAGS) -c -o test_marshallers-test-marshallers.obj `if test -f 'test-marshallers.c'; then $(CYGPATH_W) 'test-marshallers.c'; else $(CYGPATH_W) '$(srcdir)/test-marshallers.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +test_logging.log: test_logging$(EXEEXT) + @p='test_logging$(EXEEXT)'; \ + b='test_logging'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +test_marshallers.log: test_marshallers$(EXEEXT) + @p='test_marshallers$(EXEEXT)'; \ + b='test_marshallers'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Note despite being autogenerated these are not part of CLEANFILES, they are +# actually a part of EXTRA_DIST, to avoid the need for pyparser by end users +generated_test_marshallers.c: $(srcdir)/test-marshallers.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers --server --include test-marshallers.h $< $@ >/dev/null +generated_test_marshallers.h: $(srcdir)/test-marshallers.proto $(MARSHALLERS_DEPS) + $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers --server --include test-marshallers.h -H $< $@ >/dev/null + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/spice-common/tests/generated_test_marshallers.c b/spice-common/tests/generated_test_marshallers.c new file mode 100644 index 0000000..82944ed --- /dev/null +++ b/spice-common/tests/generated_test_marshallers.c @@ -0,0 +1,58 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "common/marshaller.h" + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#pragma warning(disable:4018) +#endif + +SPICE_GNUC_UNUSED static void spice_marshall_array_uint64(SpiceMarshaller *m, uint64_t *ptr, unsigned count) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + uint32_t i; + + for (i = 0; i < count; i++) { + spice_marshaller_add_uint64(m, *ptr++); + } +} + +void spice_marshall_msg_main_ShortDataSubMarshall(SPICE_GNUC_UNUSED SpiceMarshaller *m, SPICE_GNUC_UNUSED SpiceMsgMainShortDataSubMarshall *msg) +{ + SPICE_GNUC_UNUSED SpiceMarshaller *m2; + SpiceMsgMainShortDataSubMarshall *src; + src = (SpiceMsgMainShortDataSubMarshall *)msg; + + spice_marshaller_add_uint32(m, src->data_size); + m2 = spice_marshaller_get_ptr_submarshaller(m, 0); + if (src->data != NULL) { + spice_marshall_array_uint64(m2, src->data, src->data_size); + } +} + diff --git a/spice-common/tests/generated_test_marshallers.h b/spice-common/tests/generated_test_marshallers.h new file mode 100644 index 0000000..f33370f --- /dev/null +++ b/spice-common/tests/generated_test_marshallers.h @@ -0,0 +1,26 @@ +/* this is a file autogenerated by spice_codegen.py */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include +#include +#include "common/marshaller.h" + +#ifndef _GENERATED_HEADERS_H +#define _GENERATED_HEADERS_H +void spice_marshall_msg_main_ShortDataSubMarshall(SpiceMarshaller *m, SpiceMsgMainShortDataSubMarshall *msg); +#endif diff --git a/spice-common/tests/test-logging.c b/spice-common/tests/test-logging.c new file mode 100644 index 0000000..1ae4e00 --- /dev/null +++ b/spice-common/tests/test-logging.c @@ -0,0 +1,406 @@ +/* + Copyright (C) 2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#define G_LOG_DOMAIN "Spice" +#define SPICE_LOG_DOMAIN G_LOG_DOMAIN + +#include +#include + +#include "common/log.h" + +#define OTHER_LOG_DOMAIN "Other" +#define LOG_OTHER_HELPER(suffix, level) \ + static void G_PASTE(other_, suffix)(const gchar *format, ...) \ + { \ + va_list args; \ + \ + va_start (args, format); \ + g_logv(OTHER_LOG_DOMAIN, G_PASTE(G_LOG_LEVEL_, level), format, args); \ + va_end (args); \ + } + +/* Set of helpers to log in a different log domain than "Spice" */ +LOG_OTHER_HELPER(debug, DEBUG) +LOG_OTHER_HELPER(info, INFO) +LOG_OTHER_HELPER(message, MESSAGE) +LOG_OTHER_HELPER(warning, WARNING) +LOG_OTHER_HELPER(critical, CRITICAL) + +#if GLIB_CHECK_VERSION(2,38,0) +/* Checks that spice_warning() aborts after changing SPICE_ABORT_LEVEL */ +static void test_spice_abort_level(void) +{ + if (g_test_subprocess()) { + spice_warning("spice_warning"); + return; + } + /* 2 = SPICE_LOG_LEVEL_WARNING */ + g_setenv("SPICE_ABORT_LEVEL", "2", TRUE); + g_test_trap_subprocess(NULL, 0, 0); + g_unsetenv("SPICE_ABORT_LEVEL"); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*SPICE_ABORT_LEVEL*deprecated*"); + g_test_trap_assert_stderr("*spice_warning*"); +} + +/* Checks that g_warning() aborts after changing SPICE_ABORT_LEVEL */ +static void test_spice_abort_level_g_warning(void) +{ + if (g_test_subprocess()) { + g_warning("g_warning"); + return; + } + g_setenv("SPICE_ABORT_LEVEL", "2", TRUE); + g_test_trap_subprocess(NULL, 0, 0); + g_unsetenv("SPICE_ABORT_LEVEL"); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*SPICE_ABORT_LEVEL*deprecated*"); + g_test_trap_assert_stderr("*g_warning*"); +} + +/* Checks that spice_warning() aborts after setting G_DEBUG=fatal-warnings */ +static void test_spice_fatal_warning(void) +{ + g_setenv("G_DEBUG", "fatal-warnings", TRUE); + if (g_test_subprocess()) { + spice_warning("spice_warning"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*spice_warning*"); + g_unsetenv("G_DEBUG"); +} + +/* Checks that spice_critical() aborts by default if SPICE_DISABLE_ABORT is not + * defined at compile-time */ +static void test_spice_fatal_critical(void) +{ + if (g_test_subprocess()) { + spice_critical("spice_critical"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); +#ifdef SPICE_DISABLE_ABORT + g_test_trap_assert_passed(); +#else + g_test_trap_assert_failed(); +#endif + g_test_trap_assert_stderr("*spice_critical*"); +} + +/* Checks that g_critical() does not abort by default */ +static void test_spice_non_fatal_g_critical(void) +{ + if (g_test_subprocess()) { + g_critical("g_critical"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*g_critical*"); +} + +/* Checks that g_critical() aborts after setting G_DEBUG=fatal-criticals */ +static void test_spice_fatal_g_critical(void) +{ + g_setenv("G_DEBUG", "fatal-criticals", TRUE); + if (g_test_subprocess()) { + g_critical("g_critical"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); + g_test_trap_assert_stderr("*g_critical*"); + g_unsetenv("G_DEBUG"); +} + +/* Checks that spice_return_if_fail() aborts by default unless + * SPICE_DISABLE_ABORT was defined at compile time*/ +static void test_spice_fatal_return_if_fail(void) +{ + if (g_test_subprocess()) { + spice_return_if_fail(FALSE); + return; + } + g_test_trap_subprocess(NULL, 0, 0); +#ifdef SPICE_DISABLE_ABORT + g_test_trap_assert_passed(); +#else + g_test_trap_assert_failed(); +#endif + g_test_trap_assert_stderr("*test_spice_fatal_return_if_fail*"); +} + +/* Checks that g_return_if_fail() does not abort by default */ +static void test_spice_non_fatal_g_return_if_fail(void) +{ + if (g_test_subprocess()) { + g_return_if_fail(FALSE); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); +} + +/* Checks that spice_*, g_* and other_* (different log domain as g_*) all + * go through g_log() with the correct domain/log level. This then checks + * that only logs with level 'message' or higher are shown by default. + */ +static void test_log_levels(void) +{ + if (g_test_subprocess()) { + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*spice_warning"); + spice_warning("spice_warning"); + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*spice_info"); + spice_info("spice_info"); + g_test_expect_message(SPICE_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*spice_debug"); + spice_debug("spice_debug"); + + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "*g_critical"); + g_critical("g_critical"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*g_warning"); + g_warning("g_warning"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_MESSAGE, + "*g_message"); + g_message("g_message"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*g_info"); + g_info("g_info"); + g_test_expect_message(G_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*g_debug"); + g_debug("g_debug"); + + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "*other_critical"); + other_critical("other_critical"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_WARNING, + "*other_warning"); + other_warning("other_warning"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_MESSAGE, + "*other_message"); + other_message("other_message"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_INFO, + "*other_info"); + other_info("other_info"); + g_test_expect_message(OTHER_LOG_DOMAIN, + G_LOG_LEVEL_DEBUG, + "*other_debug"); + other_debug("other_debug"); + + g_test_assert_expected_messages(); + + + /* g_test_expected_message only checks whether the appropriate messages got up to g_log() + * The following calls will be caught by the parent process to check what was (not) printed + * to stdout/stderr + */ + spice_warning("spice_warning"); + spice_info("spice_info"); + spice_debug("spice_debug"); + + g_critical("g_critical"); + g_warning("g_warning"); + g_message("g_message"); + g_info("g_info"); + g_debug("g_debug"); + + other_critical("other_critical"); + other_warning("other_warning"); + other_message("other_message"); + other_info("other_info"); + other_debug("other_debug"); + + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*spice_warning\n*g_critical\n*g_warning\n*g_message\n*other_critical\n*other_warning\n*other_message\n"); +} + +/* Checks that SPICE_DEBUG_LEVEL impacts spice_debug(), g_debug() but not other_debug() */ +static void test_spice_debug_level(void) +{ + if (g_test_subprocess()) { + /* g_test_expected_message only checks whether the appropriate messages got up to g_log() + * The following calls will be caught by the parent process to check what was (not) printed + * to stdout/stderr + */ + spice_info("spice_info"); + g_debug("g_debug"); + spice_debug("spice_debug"); + other_debug("other_debug"); + + return; + } + + g_unsetenv("G_MESSAGES_DEBUG"); + g_setenv("SPICE_DEBUG_LEVEL", "5", TRUE); + g_test_trap_subprocess(NULL, 0, 0); + g_unsetenv("SPICE_DEBUG_LEVEL"); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*SPICE_DEBUG_LEVEL*deprecated*"); + g_test_trap_assert_stdout("*spice_info\n*g_debug\n*spice_debug\n"); +} + +/* Checks that raising SPICE_DEBUG_LEVEL allows to only show spice_warning() and spice_critical() + * messages, as well as g_warning() and g_critical(), but does not impact other_message() + */ +static void test_spice_debug_level_warning(void) +{ + if (g_test_subprocess()) { + spice_info("spice_info"); + spice_debug("spice_debug"); + spice_warning("spice_warning"); + spice_critical("spice_critical"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + g_warning("g_warning"); + g_critical("g_critical"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + other_warning("other_warning"); + other_critical("other_critical"); + + return; + } + + g_setenv("SPICE_ABORT_LEVEL", "0", TRUE); + g_setenv("SPICE_DEBUG_LEVEL", "1", TRUE); + g_test_trap_subprocess(NULL, 0, 0); + g_unsetenv("SPICE_ABORT_LEVEL"); + g_unsetenv("SPICE_DEBUG_LEVEL"); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("*SPICE_DEBUG_LEVEL*deprecated*"); + g_test_trap_assert_stderr("*SPICE_ABORT_LEVEL*deprecated*"); + g_test_trap_assert_stderr("*spice_critical\n*g_critical\n*other_message\n*other_warning\n*other_critical\n"); +} + +/* Checks that setting G_MESSAGES_DEBUG to 'Spice' impacts spice_debug() and + * g_debug() but not other_debug() */ +static void test_spice_g_messages_debug(void) +{ + if (g_test_subprocess()) { + g_setenv("G_MESSAGES_DEBUG", "Spice", TRUE); + + spice_debug("spice_debug"); + spice_info("spice_info"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("*spice_debug\n*spice_info\n*g_debug\n*g_info\n"); + g_test_trap_assert_stderr("*g_message\n*other_message\n"); +} + +/* Checks that setting G_MESSAGES_DEBUG to 'all' impacts spice_debug(), + * g_debug() and other_debug() */ +static void test_spice_g_messages_debug_all(void) +{ + if (g_test_subprocess()) { + g_setenv("G_MESSAGES_DEBUG", "all", TRUE); + + spice_debug("spice_debug"); + spice_info("spice_info"); + g_debug("g_debug"); + g_info("g_info"); + g_message("g_message"); + other_debug("other_debug"); + other_info("other_info"); + other_message("other_message"); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stdout("*spice_debug\n*spice_info\n*g_debug\n*g_info\n*other_debug\n*other_info\n"); + g_test_trap_assert_stderr("*g_message\n*other_message\n"); +} +#endif /* GLIB_CHECK_VERSION(2,38,0) */ + +static void handle_sigabrt(int sig) +{ + _Exit(1); +} + +int main(int argc, char **argv) +{ + GLogLevelFlags fatal_mask; + + /* prevents core generations as this could cause some issues/timeout + * depending on system configuration */ + signal(SIGABRT, handle_sigabrt); + + fatal_mask = (GLogLevelFlags)g_log_set_always_fatal((GLogLevelFlags) G_LOG_FATAL_MASK); + + g_test_init(&argc, &argv, NULL); + + /* Reset fatal mask set by g_test_init() as we don't want + * warnings/criticals to be fatal by default since this is what some of the + * test cases are going to test */ + g_log_set_always_fatal(fatal_mask & G_LOG_LEVEL_MASK); + +#if GLIB_CHECK_VERSION(2,38,0) + g_test_add_func("/spice-common/spice-abort-level", test_spice_abort_level); + g_test_add_func("/spice-common/spice-abort-level-gwarning", test_spice_abort_level_g_warning); + g_test_add_func("/spice-common/spice-debug-level", test_spice_debug_level); + g_test_add_func("/spice-common/spice-debug-level-warning", test_spice_debug_level_warning); + g_test_add_func("/spice-common/spice-g-messages-debug", test_spice_g_messages_debug); + g_test_add_func("/spice-common/spice-g-messages-debug-all", test_spice_g_messages_debug_all); + g_test_add_func("/spice-common/spice-log-levels", test_log_levels); + g_test_add_func("/spice-common/spice-fatal-critical", test_spice_fatal_critical); + g_test_add_func("/spice-common/spice-non-fatal-gcritical", test_spice_non_fatal_g_critical); + g_test_add_func("/spice-common/spice-fatal-gcritical", test_spice_fatal_g_critical); + g_test_add_func("/spice-common/spice-fatal-return-if-fail", test_spice_fatal_return_if_fail); + g_test_add_func("/spice-common/spice-non-fatal-greturn-if-fail", test_spice_non_fatal_g_return_if_fail); + g_test_add_func("/spice-common/spice-fatal-warning", test_spice_fatal_warning); +#endif /* GLIB_CHECK_VERSION(2,38,0) */ + + return g_test_run(); +} diff --git a/spice-common/tests/test-marshallers.c b/spice-common/tests/test-marshallers.c new file mode 100644 index 0000000..0026b61 --- /dev/null +++ b/spice-common/tests/test-marshallers.c @@ -0,0 +1,43 @@ +#include +#include + +#include "common/marshaller.h" +#include "generated_test_marshallers.h" + +#ifndef g_assert_true +#define g_assert_true g_assert +#endif + +static uint8_t expected_data[] = { 0x02, 0x00, 0x00, 0x00, /* data_size */ + 0x08, 0x00, 0x00, 0x00, /* data offset */ + 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, /* data */ + 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, /* data */ +}; + +int main(int argc, char **argv) +{ + SpiceMarshaller *marshaller; + SpiceMsgMainShortDataSubMarshall *msg; + size_t len; + int free_res; + uint8_t *data; + + msg = spice_malloc0(sizeof(SpiceMsgMainShortDataSubMarshall) + 2 * sizeof(uint64_t)); + msg->data_size = 2; + msg->data[0] = 0x1234567890abcdef; + msg->data[1] = 0x1234567890abcdef; + + marshaller = spice_marshaller_new(); + spice_marshall_msg_main_ShortDataSubMarshall(marshaller, msg); + spice_marshaller_flush(marshaller); + data = spice_marshaller_linearize(marshaller, 0, &len, &free_res); + g_assert_cmpint(len, ==, G_N_ELEMENTS(expected_data)); + g_assert_true(memcmp(data, expected_data, len) == 0); + if (free_res) { + free(data); + } + spice_marshaller_destroy(marshaller); + free(msg); + + return 0; +} diff --git a/spice-common/tests/test-marshallers.h b/spice-common/tests/test-marshallers.h new file mode 100644 index 0000000..9cd34c7 --- /dev/null +++ b/spice-common/tests/test-marshallers.h @@ -0,0 +1,11 @@ +#include + +#ifndef _H_TEST_MARSHALLERS + +typedef struct { + uint32_t data_size; + uint64_t data[]; +} SpiceMsgMainShortDataSubMarshall; + +#endif /* _H_TEST_MARSHALLERS */ + diff --git a/spice-common/tests/test-marshallers.proto b/spice-common/tests/test-marshallers.proto new file mode 100644 index 0000000..e360b09 --- /dev/null +++ b/spice-common/tests/test-marshallers.proto @@ -0,0 +1,10 @@ +channel TestChannel { + message { + uint32 data_size; + uint64 *data[data_size] @marshall; + } ShortDataSubMarshall; +}; + +protocol Spice { + TestChannel main = 1; +}; diff --git a/spice-controller.pc.in b/spice-controller.pc.in new file mode 100644 index 0000000..7dfe4b4 --- /dev/null +++ b/spice-controller.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: spice-controller +Description: SPICE Client controller library +Version: @VERSION@ + +Requires: glib-2.0 +Libs: -L${libdir} -lspice-controller +Cflags: -I${includedir}/spice-controller diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..6fb8507 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,656 @@ +NULL = +SUBDIRS = + +if WITH_CONTROLLER +SUBDIRS += controller +endif + +# Avoid need for perl(Text::CSV) by end users +KEYMAPS = \ + vncdisplaykeymap_xorgevdev2xtkbd.c \ + vncdisplaykeymap_xorgkbd2xtkbd.c \ + vncdisplaykeymap_xorgxquartz2xtkbd.c \ + vncdisplaykeymap_xorgxwin2xtkbd.c \ + vncdisplaykeymap_osx2xtkbd.c \ + vncdisplaykeymap_win322xtkbd.c \ + vncdisplaykeymap_x112xtkbd.c \ + $(NULL) + +# End users build dependencies can be cleaned +GLIBGENS = \ + spice-glib-enums.c \ + spice-glib-enums.h \ + spice-marshal.c \ + spice-marshal.h \ + spice-widget-enums.c \ + spice-widget-enums.h \ + $(NULL) + +CLEANFILES = $(GLIBGENS) +BUILT_SOURCES = $(GLIBGENS) $(KEYMAPS) + +EXTRA_DIST = \ + $(KEYMAPS) \ + decode-glz-tmpl.c \ + keymap-gen.pl \ + keymaps.csv \ + map-file \ + spice-glib-sym-file \ + spice-gtk-sym-file \ + spice-client-gtk-manual.defs \ + spice-client-gtk.override \ + spice-marshal.txt \ + spice-version.h.in \ + $(NULL) + +DISTCLEANFILES = spice-version.h + +bin_PROGRAMS = spicy-stats spicy-screenshot +if WITH_GTK +bin_PROGRAMS += spicy +endif +if WITH_POLKIT +acldir = $(ACL_HELPER_DIR) +acl_PROGRAMS = spice-client-glib-usb-acl-helper +endif + +lib_LTLIBRARIES = libspice-client-glib-2.0.la + +if WITH_GTK +lib_LTLIBRARIES += libspice-client-gtk-3.0.la +endif + +if HAVE_LD_VERSION_SCRIPT +GLIB_SYMBOLS_LDFLAGS = -Wl,--version-script=${srcdir}/map-file +GLIB_SYMBOLS_FILE = map-file +GTK_SYMBOLS_LDFLAGS = $(GLIB_SYMBOLS_LDFLAGS) +GTK_SYMBOLS_FILE = $(GLIB_SYMBOLS_FILE) +else +GLIB_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-glib-sym-file +GLIB_SYMBOLS_FILE = spice-glib-sym-file +GTK_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-gtk-sym-file +GTK_SYMBOLS_FILE = spice-gtk-sym-file +endif + +KEYMAP_GEN = $(srcdir)/keymap-gen.pl + +SPICE_COMMON_CPPFLAGS = \ + -DSPICE_COMPILATION \ + -DG_LOG_DOMAIN=\"GSpice\" \ + -DSPICE_NO_DEPRECATED \ + -DSPICE_GTK_LOCALEDIR=\"${SPICE_GTK_LOCALEDIR}\" \ + -DPNP_IDS=\""$(PNP_IDS)"\" \ + -DUSB_IDS=\""$(USB_IDS)"\" \ + -DSPICE_DISABLE_ABORT \ + -I$(top_srcdir) \ + $(COMMON_CFLAGS) \ + $(PIXMAN_CFLAGS) \ + $(PULSE_CFLAGS) \ + $(GTK_CFLAGS) \ + $(CAIRO_CFLAGS) \ + $(GLIB2_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GOBJECT2_CFLAGS) \ + $(SSL_CFLAGS) \ + $(SASL_CFLAGS) \ + $(GSTAUDIO_CFLAGS) \ + $(GSTVIDEO_CFLAGS) \ + $(SMARTCARD_CFLAGS) \ + $(USBREDIR_CFLAGS) \ + $(GUDEV_CFLAGS) \ + $(SOUP_CFLAGS) \ + $(PHODAV_CFLAGS) \ + $(LZ4_CFLAGS) \ + $(NULL) + +AM_CPPFLAGS = \ + $(SPICE_COMMON_CPPFLAGS) \ + $(SPICE_CFLAGS) \ + $(NULL) + +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +SPICE_GTK_LDFLAGS_COMMON = \ + -version-info 5:0:0 \ + -no-undefined \ + $(GTK_SYMBOLS_LDFLAGS) \ + $(NULL) + +SPICE_GTK_LIBADD_COMMON = \ + libspice-client-glib-2.0.la \ + $(GTK_LIBS) \ + $(CAIRO_LIBS) \ + $(LIBM) \ + $(NULL) + +SPICE_GTK_SOURCES_COMMON = \ + spice-util.c \ + spice-util-priv.h \ + spice-gtk-session.c \ + spice-gtk-session-priv.h \ + spice-widget.c \ + spice-widget-priv.h \ + spice-file-transfer-task.h \ + vncdisplaykeymap.c \ + vncdisplaykeymap.h \ + spice-grabsequence.c \ + spice-grabsequence.h \ + spice-grabsequence-priv.h \ + desktop-integration.c \ + desktop-integration.h \ + usb-device-widget.c \ + $(NULL) + +nodist_SPICE_GTK_SOURCES_COMMON = \ + spice-widget-enums.c \ + spice-marshal.c \ + $(NULL) + +SPICE_GTK_SOURCES_COMMON += \ + spice-widget-cairo.c \ + $(NULL) + +if !OS_WIN32 +SPICE_GTK_SOURCES_COMMON += \ + spice-widget-egl.c \ + $(NULL) +endif + +if WITH_GTK +EXTRA_libspice_client_gtk_3_0_la_DEPENDENCIES = $(GTK_SYMBOLS_FILE) +libspice_client_gtk_3_0_la_LDFLAGS = $(SPICE_GTK_LDFLAGS_COMMON) +libspice_client_gtk_3_0_la_LIBADD = $(SPICE_GTK_LIBADD_COMMON) +libspice_client_gtk_3_0_la_SOURCES = $(SPICE_GTK_SOURCES_COMMON) +nodist_libspice_client_gtk_3_0_la_SOURCES = $(nodist_SPICE_GTK_SOURCES_COMMON) + +libspice_client_gtkincludedir = $(includedir)/spice-client-gtk-3.0 +libspice_client_gtkinclude_HEADERS = \ + spice-client-gtk.h \ + spice-gtk-session.h \ + spice-widget.h \ + spice-grabsequence.h \ + usb-device-widget.h \ + $(NULL) + +nodist_libspice_client_gtkinclude_HEADERS = \ + spice-widget-enums.h \ + $(NULL) +endif + +EXTRA_libspice_client_glib_2_0_la_DEPENDENCIES = $(GLIB_SYMBOLS_FILE) + +libspice_client_glib_2_0_la_LDFLAGS = \ + -version-info 13:0:5 \ + -no-undefined \ + $(GLIB_SYMBOLS_LDFLAGS) \ + $(NULL) + +libspice_client_glib_2_0_la_LIBADD = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/spice-common/common/libspice-common-client.la \ + $(GLIB2_LIBS) \ + $(SOUP_LIBS) \ + $(GIO_LIBS) \ + $(GOBJECT2_LIBS) \ + $(JPEG_LIBS) \ + $(Z_LIBS) \ + $(LZ4_LIBS) \ + $(PIXMAN_LIBS) \ + $(SSL_LIBS) \ + $(PULSE_LIBS) \ + $(GSTAUDIO_LIBS) \ + $(GSTVIDEO_LIBS) \ + $(SASL_LIBS) \ + $(SMARTCARD_LIBS) \ + $(USBREDIR_LIBS) \ + $(GUDEV_LIBS) \ + $(PHODAV_LIBS) \ + $(NULL) + +if WITH_POLKIT +USB_ACL_HELPER_SRCS = \ + usb-acl-helper.c \ + usb-acl-helper.h \ + $(NULL) +AM_CPPFLAGS += -DACL_HELPER_PATH="\"$(ACL_HELPER_DIR)\"" +else +USB_ACL_HELPER_SRCS = +endif + +libspice_client_glib_2_0_la_SOURCES = \ + bio-gio.c \ + bio-gio.h \ + spice-audio.c \ + spice-audio-priv.h \ + spice-common.h \ + spice-util.c \ + spice-util-priv.h \ + spice-option.h \ + spice-option.c \ + \ + spice-client.c \ + spice-session.c \ + spice-session-priv.h \ + spice-channel.c \ + spice-channel-cache.h \ + spice-channel-priv.h \ + coroutine.h \ + gio-coroutine.c \ + gio-coroutine.h \ + \ + channel-base.c \ + channel-webdav.c \ + channel-cursor.c \ + channel-display.c \ + channel-display-priv.h \ + channel-inputs.c \ + channel-main.c \ + channel-playback.c \ + channel-playback-priv.h \ + channel-port.c \ + channel-record.c \ + channel-smartcard.c \ + channel-usbredir.c \ + channel-usbredir-priv.h \ + smartcard-manager.c \ + smartcard-manager-priv.h \ + spice-uri.c \ + spice-uri-priv.h \ + usb-device-manager.c \ + usb-device-manager-priv.h \ + usbutil.c \ + usbutil.h \ + $(USB_ACL_HELPER_SRCS) \ + vmcstream.c \ + vmcstream.h \ + wocky-http-proxy.c \ + wocky-http-proxy.h \ + \ + decode.h \ + decode-glz.c \ + decode-jpeg.c \ + decode-zlib.c \ + \ + client_sw_canvas.c \ + client_sw_canvas.h \ + $(NULL) + +nodist_libspice_client_glib_2_0_la_SOURCES = \ + spice-glib-enums.c \ + spice-marshal.c \ + spice-marshal.h \ + $(NULL) + +libspice_client_glibincludedir = $(includedir)/spice-client-glib-2.0 +libspice_client_glibinclude_HEADERS = \ + spice-audio.h \ + spice-client.h \ + spice-uri.h \ + spice-types.h \ + spice-session.h \ + spice-channel.h \ + spice-util.h \ + spice-option.h \ + spice-version.h \ + channel-cursor.h \ + channel-display.h \ + channel-inputs.h \ + channel-main.h \ + channel-playback.h \ + channel-port.h \ + channel-record.h \ + channel-smartcard.h \ + channel-usbredir.h \ + channel-webdav.h \ + usb-device-manager.h \ + smartcard-manager.h \ + spice-file-transfer-task.h \ + $(NULL) + +nodist_libspice_client_glibinclude_HEADERS = \ + spice-glib-enums.h \ + $(NULL) + +# file for API compatibility, but we don't want warning during our compilation +dist_libspice_client_glibinclude_DATA = \ + spice-channel-enums.h \ + $(NULL) + +if HAVE_PULSE +libspice_client_glib_2_0_la_SOURCES += \ + spice-pulse.c \ + spice-pulse.h \ + $(NULL) +endif + +if HAVE_GSTAUDIO +libspice_client_glib_2_0_la_SOURCES += \ + spice-gstaudio.c \ + spice-gstaudio.h \ + $(NULL) +endif + +if HAVE_BUILTIN_MJPEG +libspice_client_glib_2_0_la_SOURCES += \ + channel-display-mjpeg.c \ + $(NULL) +endif + +if HAVE_GSTVIDEO +libspice_client_glib_2_0_la_SOURCES += \ + channel-display-gst.c \ + $(NULL) +endif + +if WITH_PHODAV +libspice_client_glib_2_0_la_SOURCES += \ + giopipe.c \ + giopipe.h \ + $(NULL) +endif + +if WITH_UCONTEXT +libspice_client_glib_2_0_la_SOURCES += continuation.h continuation.c coroutine_ucontext.c +endif + +if WITH_WINFIBER +libspice_client_glib_2_0_la_SOURCES += coroutine_winfibers.c +endif + +if WITH_GTHREAD +libspice_client_glib_2_0_la_SOURCES += coroutine_gthread.c +libspice_client_glib_2_0_la_LIBADD += $(GTHREAD_LIBS) +endif + + +WIN_USB_FILES= \ + win-usb-dev.h \ + win-usb-dev.c \ + win-usb-clerk.h \ + win-usb-driver-install.h \ + win-usb-driver-install.c \ + usbdk_api.h \ + usbdk_api.c \ + $(NULL) + +if OS_WIN32 +if WITH_USBREDIR +libspice_client_glib_2_0_la_SOURCES += \ + $(WIN_USB_FILES) +endif +libspice_client_glib_2_0_la_LIBADD += -lws2_32 -lgdi32 +endif + +spicy_SOURCES = \ + spicy.c \ + spicy-connect.h \ + spicy-connect.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_LDADD = \ + libspice-client-gtk-3.0.la \ + libspice-client-glib-2.0.la \ + $(GTHREAD_LIBS) \ + $(GTK_LIBS) \ + $(LIBM) \ + $(NULL) + +spicy_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(GTHREAD_CFLAGS) \ + -DSPICE_DISABLE_DEPRECATED \ + $(NULL) + + +if WITH_POLKIT +spice_client_glib_usb_acl_helper_SOURCES = \ + spice-client-glib-usb-acl-helper.c \ + $(NULL) + +spice_client_glib_usb_acl_helper_LDADD = \ + $(GLIB2_LIBS) \ + $(GIO_LIBS) \ + $(POLKIT_LIBS) \ + $(ACL_LIBS) \ + $(PIE_LDFLAGS) \ + $(NULL) + +spice_client_glib_usb_acl_helper_CPPFLAGS = \ + $(SPICE_CFLAGS) \ + $(GLIB2_CFLAGS) \ + $(GIO_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(PIE_CFLAGS) \ + $(NULL) + +install-data-hook: + -chown root $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper + -chmod u+s $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper + +endif + + +spicy_screenshot_SOURCES = \ + spicy-screenshot.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_screenshot_LDADD = \ + libspice-client-glib-2.0.la \ + $(GOBJECT2_LIBS) \ + $(NULL) + +spicy_stats_SOURCES = \ + spicy-stats.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_stats_LDADD = \ + libspice-client-glib-2.0.la \ + $(GOBJECT2_LIBS) \ + $(NULL) + + + +$(libspice_client_glib_2_0_la_SOURCES): spice-glib-enums.h spice-marshal.h + +if WITH_GTK +$(libspice_client_gtk_3_0_la_SOURCES): spice-glib-enums.h spice-widget-enums.h +endif + +spice-marshal.c: spice-marshal.h +spice-glib-enums.c: spice-glib-enums.h +spice-widget-enums.c: spice-widget-enums.h + +spice-marshal.c: spice-marshal.txt + $(AM_V_GEN)echo "#include \"config.h\"" > $@ && \ + echo "#include \"spice-marshal.h\"" > $@ && \ + glib-genmarshal --body $< >> $@ || (rm -f $@ && exit 1) + +spice-marshal.h: spice-marshal.txt + $(AM_V_GEN)glib-genmarshal --header $< > $@ || (rm -f $@ && exit 1) + +spice-glib-enums.c: spice-channel.h channel-inputs.h spice-session.h + $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \ + --fhead "#include \n" \ + --fhead "#include \"spice-glib-enums.h\"\n\n" \ + --fprod "\n#include \"spice-session.h\"\n" \ + --fprod "\n#include \"spice-channel.h\"\n" \ + --fprod "\n#include \"channel-inputs.h\"\n" \ + --vhead "static const G@Type@Value _@enum_name@_values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n};\n\n" \ + --vtail "GType\n@enum_name@_get_type (void)\n{\n" \ + --vtail " static GType type = 0;\n" \ + --vtail " static volatile gsize type_volatile = 0;\n\n" \ + --vtail " if (g_once_init_enter(&type_volatile)) {\n" \ + --vtail " type = g_@type@_register_static (\"@EnumName@\", _@enum_name@_values);\n" \ + --vtail " g_once_init_leave(&type_volatile, type);\n" \ + --vtail " }\n\n" \ + --vtail " return type;\n}\n\n" \ + $^ > $@ + +spice-glib-enums.h: spice-channel.h channel-inputs.h spice-session.h + $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_GLIB_ENUMS_H\n" \ + --fhead "#define SPICE_GLIB_ENUMS_H\n\n" \ + --fhead "G_BEGIN_DECLS\n\n" \ + --ftail "G_END_DECLS\n\n" \ + --ftail "#endif /* SPICE_CHANNEL_ENUMS_H */\n" \ + --eprod "#define SPICE_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \ + --eprod "GType @enum_name@_get_type (void);\n" \ + $^ > $@ + +spice-widget-enums.c: spice-widget.h + $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \ + --fhead "#include \n" \ + --fhead "#include \"spice-widget-enums.h\"\n\n" \ + --fprod "\n#include \"spice-widget.h\"\n" \ + --vhead "static const G@Type@Value _@enum_name@_values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n};\n\n" \ + --vtail "GType\n@enum_name@_get_type (void)\n{\n" \ + --vtail " static GType type = 0;\n" \ + --vtail " static volatile gsize type_volatile = 0;\n\n" \ + --vtail " if (g_once_init_enter(&type_volatile)) {\n" \ + --vtail " type = g_@type@_register_static (\"@EnumName@\", _@enum_name@_values);\n" \ + --vtail " g_once_init_leave(&type_volatile, type);\n" \ + --vtail " }\n\n" \ + --vtail " return type;\n}\n\n" \ + $< > $@ + +spice-widget-enums.h: spice-widget.h + $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_WIDGET_ENUMS_H\n" \ + --fhead "#define SPICE_WIDGET_ENUMS_H\n\n" \ + --fhead "G_BEGIN_DECLS\n\n" \ + --ftail "G_END_DECLS\n\n" \ + --ftail "#endif /* SPICE_WIDGET_ENUMS_H */\n" \ + --eprod "#define SPICE_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \ + --eprod "GType @enum_name@_get_type (void);\n" \ + $< > $@ + + +vncdisplaykeymap.c: $(KEYMAPS) + +$(KEYMAPS): $(KEYMAP_GEN) keymaps.csv + +# Note despite being autogenerated these are not part of CLEANFILES, they +# are actually a part of EXTRA_DIST to avoid the need for perl(Text::CSV) by +# end users +vncdisplaykeymap_xorgevdev2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgevdev xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgkbd2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgkbd xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgxquartz2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxquartz xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgxwin2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxwin xtkbd > $@ || rm $@ + +vncdisplaykeymap_osx2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv osx xtkbd > $@ || rm $@ + +vncdisplaykeymap_win322xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv win32 xtkbd > $@ || rm $@ + +vncdisplaykeymap_x112xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv x11 xtkbd > $@ || rm $@ + +-include $(INTROSPECTION_MAKEFILE) + +if G_IR_SCANNER_SYMBOL_PREFIX +PREFIX_ARGS = --symbol-prefix=spice --identifier-prefix=Spice +else +PREFIX_ARGS = --strip-prefix=Spice +endif + +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --warn-all --accept-unprefixed --add-include-path=$(builddir) $(PREFIX_ARGS) +INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) + +if HAVE_INTROSPECTION +glib_introspection_files = \ + $(libspice_client_glibinclude_HEADERS) \ + $(nodist_libspice_client_glibinclude_HEADERS) \ + spice-audio.c \ + spice-client.c \ + spice-session.c \ + spice-channel.c \ + spice-glib-enums.c \ + spice-option.c \ + spice-util.c \ + channel-webdav.c \ + channel-cursor.c \ + channel-display.c \ + channel-inputs.c \ + channel-main.c \ + channel-playback.c \ + channel-port.c \ + channel-record.c \ + channel-smartcard.c \ + channel-usbredir.c \ + smartcard-manager.c \ + usb-device-manager.c \ + $(NULL) + +gtk_introspection_files = \ + $(libspice_client_gtkinclude_HEADERS) \ + $(nodist_libspice_client_gtkinclude_HEADERS) \ + spice-gtk-session.c \ + spice-widget.c \ + spice-grabsequence.c \ + usb-device-widget.c \ + $(NULL) + +SpiceClientGLib-2.0.gir: libspice-client-glib-2.0.la +SpiceClientGLib_2_0_gir_INCLUDES = GObject-2.0 Gio-2.0 +SpiceClientGLib_2_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS) +SpiceClientGLib_2_0_gir_LIBS = libspice-client-glib-2.0.la +SpiceClientGLib_2_0_gir_FILES = $(glib_introspection_files) +SpiceClientGLib_2_0_gir_EXPORT_PACKAGES = spice-client-glib-2.0 +SpiceClientGLib_2_0_gir_SCANNERFLAGS = --c-include="spice-client.h" +INTROSPECTION_GIRS += SpiceClientGLib-2.0.gir + +if WITH_GTK +SpiceClientGtk-3.0.gir: libspice-client-gtk-3.0.la SpiceClientGLib-2.0.gir +SpiceClientGtk_3_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 SpiceClientGLib-2.0 +SpiceClientGtk_3_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS) +SpiceClientGtk_3_0_gir_LIBS = libspice-client-gtk-3.0.la libspice-client-glib-2.0.la +SpiceClientGtk_3_0_gir_FILES = $(gtk_introspection_files) +SpiceClientGtk_3_0_gir_EXPORT_PACKAGES = spice-client-gtk-3.0 +SpiceClientGtk_3_0_gir_SCANNERFLAGS = --c-include="spice-widget.h" +INTROSPECTION_GIRS += SpiceClientGtk-3.0.gir +endif + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibsdir = $(libdir)/girepository-1.0 +typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES += $(gir_DATA) $(typelibs_DATA) +endif + +update-map-file: $(libspice_client_gtkinclude_HEADERS) $(nodist_libspice_client_gtkinclude_HEADERS) $(libspice_client_glibinclude_HEADERS) $(nodist_libspice_client_glibinclude_HEADERS) + ( echo "SPICEGTK_1 {" ; \ + echo "global:" ; \ + ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 ";" }' | sort ; \ + echo "local:" ; \ + echo "*;" ; \ + echo "};" ) > $(srcdir)/map-file + +update-glib-sym-file: $(libspice_client_glibinclude_HEADERS) $(nodist_libspice_client_glibinclude_HEADERS) + ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }' | sort ; \ + ) > $(srcdir)/spice-glib-sym-file + +update-gtk-sym-file: $(libspice_client_gtkinclude_HEADERS) $(nodist_libspice_client_gtkinclude_HEADERS) + ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }' | sort ; \ + ) > $(srcdir)/spice-gtk-sym-file + +update-symbol-files: update-map-file update-glib-sym-file update-gtk-sym-file + +-include $(top_srcdir)/git.mk diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..f8af367 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1981 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_CONTROLLER_TRUE@am__append_1 = controller +bin_PROGRAMS = spicy-stats$(EXEEXT) spicy-screenshot$(EXEEXT) \ + $(am__EXEEXT_1) +@WITH_GTK_TRUE@am__append_2 = spicy +@WITH_POLKIT_TRUE@acl_PROGRAMS = \ +@WITH_POLKIT_TRUE@ spice-client-glib-usb-acl-helper$(EXEEXT) +@WITH_GTK_TRUE@am__append_3 = libspice-client-gtk-3.0.la +@OS_WIN32_FALSE@am__append_4 = \ +@OS_WIN32_FALSE@ spice-widget-egl.c \ +@OS_WIN32_FALSE@ $(NULL) + +@WITH_POLKIT_TRUE@am__append_5 = -DACL_HELPER_PATH="\"$(ACL_HELPER_DIR)\"" +@HAVE_PULSE_TRUE@am__append_6 = \ +@HAVE_PULSE_TRUE@ spice-pulse.c \ +@HAVE_PULSE_TRUE@ spice-pulse.h \ +@HAVE_PULSE_TRUE@ $(NULL) + +@HAVE_GSTAUDIO_TRUE@am__append_7 = \ +@HAVE_GSTAUDIO_TRUE@ spice-gstaudio.c \ +@HAVE_GSTAUDIO_TRUE@ spice-gstaudio.h \ +@HAVE_GSTAUDIO_TRUE@ $(NULL) + +@HAVE_BUILTIN_MJPEG_TRUE@am__append_8 = \ +@HAVE_BUILTIN_MJPEG_TRUE@ channel-display-mjpeg.c \ +@HAVE_BUILTIN_MJPEG_TRUE@ $(NULL) + +@HAVE_GSTVIDEO_TRUE@am__append_9 = \ +@HAVE_GSTVIDEO_TRUE@ channel-display-gst.c \ +@HAVE_GSTVIDEO_TRUE@ $(NULL) + +@WITH_PHODAV_TRUE@am__append_10 = \ +@WITH_PHODAV_TRUE@ giopipe.c \ +@WITH_PHODAV_TRUE@ giopipe.h \ +@WITH_PHODAV_TRUE@ $(NULL) + +@WITH_UCONTEXT_TRUE@am__append_11 = continuation.h continuation.c coroutine_ucontext.c +@WITH_WINFIBER_TRUE@am__append_12 = coroutine_winfibers.c +@WITH_GTHREAD_TRUE@am__append_13 = coroutine_gthread.c +@WITH_GTHREAD_TRUE@am__append_14 = $(GTHREAD_LIBS) +@OS_WIN32_TRUE@@WITH_USBREDIR_TRUE@am__append_15 = \ +@OS_WIN32_TRUE@@WITH_USBREDIR_TRUE@ $(WIN_USB_FILES) + +@OS_WIN32_TRUE@am__append_16 = -lws2_32 -lgdi32 +@HAVE_INTROSPECTION_TRUE@am__append_17 = SpiceClientGLib-2.0.gir +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@am__append_18 = SpiceClientGtk-3.0.gir +@HAVE_INTROSPECTION_TRUE@am__append_19 = $(gir_DATA) $(typelibs_DATA) +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(dist_libspice_client_glibinclude_DATA) \ + $(libspice_client_glibinclude_HEADERS) \ + $(am__libspice_client_gtkinclude_HEADERS_DIST) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = spice-version.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(acldir)" \ + "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(libspice_client_glibincludedir)" \ + "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" \ + "$(DESTDIR)$(libspice_client_glibincludedir)" \ + "$(DESTDIR)$(libspice_client_gtkincludedir)" \ + "$(DESTDIR)$(libspice_client_glibincludedir)" \ + "$(DESTDIR)$(libspice_client_gtkincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +@WITH_GTHREAD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +libspice_client_glib_2_0_la_DEPENDENCIES = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/spice-common/common/libspice-common-client.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_1) +am__libspice_client_glib_2_0_la_SOURCES_DIST = bio-gio.c bio-gio.h \ + spice-audio.c spice-audio-priv.h spice-common.h spice-util.c \ + spice-util-priv.h spice-option.h spice-option.c spice-client.c \ + spice-session.c spice-session-priv.h spice-channel.c \ + spice-channel-cache.h spice-channel-priv.h coroutine.h \ + gio-coroutine.c gio-coroutine.h channel-base.c \ + channel-webdav.c channel-cursor.c channel-display.c \ + channel-display-priv.h channel-inputs.c channel-main.c \ + channel-playback.c channel-playback-priv.h channel-port.c \ + channel-record.c channel-smartcard.c channel-usbredir.c \ + channel-usbredir-priv.h smartcard-manager.c \ + smartcard-manager-priv.h spice-uri.c spice-uri-priv.h \ + usb-device-manager.c usb-device-manager-priv.h usbutil.c \ + usbutil.h usb-acl-helper.c usb-acl-helper.h vmcstream.c \ + vmcstream.h wocky-http-proxy.c wocky-http-proxy.h decode.h \ + decode-glz.c decode-jpeg.c decode-zlib.c client_sw_canvas.c \ + client_sw_canvas.h spice-pulse.c spice-pulse.h \ + spice-gstaudio.c spice-gstaudio.h channel-display-mjpeg.c \ + channel-display-gst.c giopipe.c giopipe.h continuation.h \ + continuation.c coroutine_ucontext.c coroutine_winfibers.c \ + coroutine_gthread.c win-usb-dev.h win-usb-dev.c \ + win-usb-clerk.h win-usb-driver-install.h \ + win-usb-driver-install.c usbdk_api.h usbdk_api.c +am__objects_1 = +@WITH_POLKIT_TRUE@am__objects_2 = usb-acl-helper.lo $(am__objects_1) +@HAVE_PULSE_TRUE@am__objects_3 = spice-pulse.lo $(am__objects_1) +@HAVE_GSTAUDIO_TRUE@am__objects_4 = spice-gstaudio.lo $(am__objects_1) +@HAVE_BUILTIN_MJPEG_TRUE@am__objects_5 = channel-display-mjpeg.lo \ +@HAVE_BUILTIN_MJPEG_TRUE@ $(am__objects_1) +@HAVE_GSTVIDEO_TRUE@am__objects_6 = channel-display-gst.lo \ +@HAVE_GSTVIDEO_TRUE@ $(am__objects_1) +@WITH_PHODAV_TRUE@am__objects_7 = giopipe.lo $(am__objects_1) +@WITH_UCONTEXT_TRUE@am__objects_8 = continuation.lo \ +@WITH_UCONTEXT_TRUE@ coroutine_ucontext.lo +@WITH_WINFIBER_TRUE@am__objects_9 = coroutine_winfibers.lo +@WITH_GTHREAD_TRUE@am__objects_10 = coroutine_gthread.lo +am__objects_11 = win-usb-dev.lo win-usb-driver-install.lo usbdk_api.lo \ + $(am__objects_1) +@OS_WIN32_TRUE@@WITH_USBREDIR_TRUE@am__objects_12 = $(am__objects_11) +am_libspice_client_glib_2_0_la_OBJECTS = bio-gio.lo spice-audio.lo \ + spice-util.lo spice-option.lo spice-client.lo spice-session.lo \ + spice-channel.lo gio-coroutine.lo channel-base.lo \ + channel-webdav.lo channel-cursor.lo channel-display.lo \ + channel-inputs.lo channel-main.lo channel-playback.lo \ + channel-port.lo channel-record.lo channel-smartcard.lo \ + channel-usbredir.lo smartcard-manager.lo spice-uri.lo \ + usb-device-manager.lo usbutil.lo $(am__objects_2) vmcstream.lo \ + wocky-http-proxy.lo decode-glz.lo decode-jpeg.lo \ + decode-zlib.lo client_sw_canvas.lo $(am__objects_1) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) \ + $(am__objects_6) $(am__objects_7) $(am__objects_8) \ + $(am__objects_9) $(am__objects_10) $(am__objects_12) +nodist_libspice_client_glib_2_0_la_OBJECTS = spice-glib-enums.lo \ + spice-marshal.lo $(am__objects_1) +libspice_client_glib_2_0_la_OBJECTS = \ + $(am_libspice_client_glib_2_0_la_OBJECTS) \ + $(nodist_libspice_client_glib_2_0_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libspice_client_glib_2_0_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libspice_client_glib_2_0_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__DEPENDENCIES_3 = libspice-client-glib-2.0.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +@WITH_GTK_TRUE@libspice_client_gtk_3_0_la_DEPENDENCIES = \ +@WITH_GTK_TRUE@ $(am__DEPENDENCIES_3) +am__libspice_client_gtk_3_0_la_SOURCES_DIST = spice-util.c \ + spice-util-priv.h spice-gtk-session.c spice-gtk-session-priv.h \ + spice-widget.c spice-widget-priv.h spice-file-transfer-task.h \ + vncdisplaykeymap.c vncdisplaykeymap.h spice-grabsequence.c \ + spice-grabsequence.h spice-grabsequence-priv.h \ + desktop-integration.c desktop-integration.h \ + usb-device-widget.c spice-widget-cairo.c spice-widget-egl.c +@OS_WIN32_FALSE@am__objects_13 = spice-widget-egl.lo $(am__objects_1) +am__objects_14 = spice-util.lo spice-gtk-session.lo spice-widget.lo \ + vncdisplaykeymap.lo spice-grabsequence.lo \ + desktop-integration.lo usb-device-widget.lo $(am__objects_1) \ + spice-widget-cairo.lo $(am__objects_1) $(am__objects_13) +@WITH_GTK_TRUE@am_libspice_client_gtk_3_0_la_OBJECTS = \ +@WITH_GTK_TRUE@ $(am__objects_14) +am__objects_15 = spice-widget-enums.lo spice-marshal.lo \ + $(am__objects_1) +@WITH_GTK_TRUE@nodist_libspice_client_gtk_3_0_la_OBJECTS = \ +@WITH_GTK_TRUE@ $(am__objects_15) +libspice_client_gtk_3_0_la_OBJECTS = \ + $(am_libspice_client_gtk_3_0_la_OBJECTS) \ + $(nodist_libspice_client_gtk_3_0_la_OBJECTS) +libspice_client_gtk_3_0_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libspice_client_gtk_3_0_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@WITH_GTK_TRUE@am_libspice_client_gtk_3_0_la_rpath = -rpath $(libdir) +@WITH_GTK_TRUE@am__EXEEXT_1 = spicy$(EXEEXT) +PROGRAMS = $(acl_PROGRAMS) $(bin_PROGRAMS) +am__spice_client_glib_usb_acl_helper_SOURCES_DIST = \ + spice-client-glib-usb-acl-helper.c +@WITH_POLKIT_TRUE@am_spice_client_glib_usb_acl_helper_OBJECTS = spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.$(OBJEXT) \ +@WITH_POLKIT_TRUE@ $(am__objects_1) +spice_client_glib_usb_acl_helper_OBJECTS = \ + $(am_spice_client_glib_usb_acl_helper_OBJECTS) +@WITH_POLKIT_TRUE@spice_client_glib_usb_acl_helper_DEPENDENCIES = \ +@WITH_POLKIT_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@WITH_POLKIT_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@WITH_POLKIT_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_spicy_OBJECTS = spicy-spicy.$(OBJEXT) spicy-spicy-connect.$(OBJEXT) \ + spicy-spice-cmdline.$(OBJEXT) $(am__objects_1) +spicy_OBJECTS = $(am_spicy_OBJECTS) +spicy_DEPENDENCIES = libspice-client-gtk-3.0.la \ + libspice-client-glib-2.0.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_spicy_screenshot_OBJECTS = spicy-screenshot.$(OBJEXT) \ + spice-cmdline.$(OBJEXT) $(am__objects_1) +spicy_screenshot_OBJECTS = $(am_spicy_screenshot_OBJECTS) +spicy_screenshot_DEPENDENCIES = libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_spicy_stats_OBJECTS = spicy-stats.$(OBJEXT) spice-cmdline.$(OBJEXT) \ + $(am__objects_1) +spicy_stats_OBJECTS = $(am_spicy_stats_OBJECTS) +spicy_stats_DEPENDENCIES = libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libspice_client_glib_2_0_la_SOURCES) \ + $(nodist_libspice_client_glib_2_0_la_SOURCES) \ + $(libspice_client_gtk_3_0_la_SOURCES) \ + $(nodist_libspice_client_gtk_3_0_la_SOURCES) \ + $(spice_client_glib_usb_acl_helper_SOURCES) $(spicy_SOURCES) \ + $(spicy_screenshot_SOURCES) $(spicy_stats_SOURCES) +DIST_SOURCES = $(am__libspice_client_glib_2_0_la_SOURCES_DIST) \ + $(am__libspice_client_gtk_3_0_la_SOURCES_DIST) \ + $(am__spice_client_glib_usb_acl_helper_SOURCES_DIST) \ + $(spicy_SOURCES) $(spicy_screenshot_SOURCES) \ + $(spicy_stats_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_libspice_client_glibinclude_DATA) $(gir_DATA) \ + $(typelibs_DATA) +am__libspice_client_gtkinclude_HEADERS_DIST = spice-client-gtk.h \ + spice-gtk-session.h spice-widget.h spice-grabsequence.h \ + usb-device-widget.h +HEADERS = $(libspice_client_glibinclude_HEADERS) \ + $(libspice_client_gtkinclude_HEADERS) \ + $(nodist_libspice_client_glibinclude_HEADERS) \ + $(nodist_libspice_client_gtkinclude_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = controller +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/spice-version.h.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +SUBDIRS = $(am__append_1) + +# Avoid need for perl(Text::CSV) by end users +KEYMAPS = \ + vncdisplaykeymap_xorgevdev2xtkbd.c \ + vncdisplaykeymap_xorgkbd2xtkbd.c \ + vncdisplaykeymap_xorgxquartz2xtkbd.c \ + vncdisplaykeymap_xorgxwin2xtkbd.c \ + vncdisplaykeymap_osx2xtkbd.c \ + vncdisplaykeymap_win322xtkbd.c \ + vncdisplaykeymap_x112xtkbd.c \ + $(NULL) + + +# End users build dependencies can be cleaned +GLIBGENS = \ + spice-glib-enums.c \ + spice-glib-enums.h \ + spice-marshal.c \ + spice-marshal.h \ + spice-widget-enums.c \ + spice-widget-enums.h \ + $(NULL) + +CLEANFILES = $(GLIBGENS) $(am__append_19) +BUILT_SOURCES = $(GLIBGENS) $(KEYMAPS) +EXTRA_DIST = \ + $(KEYMAPS) \ + decode-glz-tmpl.c \ + keymap-gen.pl \ + keymaps.csv \ + map-file \ + spice-glib-sym-file \ + spice-gtk-sym-file \ + spice-client-gtk-manual.defs \ + spice-client-gtk.override \ + spice-marshal.txt \ + spice-version.h.in \ + $(NULL) + +DISTCLEANFILES = spice-version.h +@WITH_POLKIT_TRUE@acldir = $(ACL_HELPER_DIR) +lib_LTLIBRARIES = libspice-client-glib-2.0.la $(am__append_3) +@HAVE_LD_VERSION_SCRIPT_FALSE@GLIB_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-glib-sym-file +@HAVE_LD_VERSION_SCRIPT_TRUE@GLIB_SYMBOLS_LDFLAGS = -Wl,--version-script=${srcdir}/map-file +@HAVE_LD_VERSION_SCRIPT_FALSE@GLIB_SYMBOLS_FILE = spice-glib-sym-file +@HAVE_LD_VERSION_SCRIPT_TRUE@GLIB_SYMBOLS_FILE = map-file +@HAVE_LD_VERSION_SCRIPT_FALSE@GTK_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-gtk-sym-file +@HAVE_LD_VERSION_SCRIPT_TRUE@GTK_SYMBOLS_LDFLAGS = $(GLIB_SYMBOLS_LDFLAGS) +@HAVE_LD_VERSION_SCRIPT_FALSE@GTK_SYMBOLS_FILE = spice-gtk-sym-file +@HAVE_LD_VERSION_SCRIPT_TRUE@GTK_SYMBOLS_FILE = $(GLIB_SYMBOLS_FILE) +KEYMAP_GEN = $(srcdir)/keymap-gen.pl +SPICE_COMMON_CPPFLAGS = \ + -DSPICE_COMPILATION \ + -DG_LOG_DOMAIN=\"GSpice\" \ + -DSPICE_NO_DEPRECATED \ + -DSPICE_GTK_LOCALEDIR=\"${SPICE_GTK_LOCALEDIR}\" \ + -DPNP_IDS=\""$(PNP_IDS)"\" \ + -DUSB_IDS=\""$(USB_IDS)"\" \ + -DSPICE_DISABLE_ABORT \ + -I$(top_srcdir) \ + $(COMMON_CFLAGS) \ + $(PIXMAN_CFLAGS) \ + $(PULSE_CFLAGS) \ + $(GTK_CFLAGS) \ + $(CAIRO_CFLAGS) \ + $(GLIB2_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GOBJECT2_CFLAGS) \ + $(SSL_CFLAGS) \ + $(SASL_CFLAGS) \ + $(GSTAUDIO_CFLAGS) \ + $(GSTVIDEO_CFLAGS) \ + $(SMARTCARD_CFLAGS) \ + $(USBREDIR_CFLAGS) \ + $(GUDEV_CFLAGS) \ + $(SOUP_CFLAGS) \ + $(PHODAV_CFLAGS) \ + $(LZ4_CFLAGS) \ + $(NULL) + +AM_CPPFLAGS = $(SPICE_COMMON_CPPFLAGS) $(SPICE_CFLAGS) $(NULL) \ + $(am__append_5) + +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +SPICE_GTK_LDFLAGS_COMMON = \ + -version-info 5:0:0 \ + -no-undefined \ + $(GTK_SYMBOLS_LDFLAGS) \ + $(NULL) + +SPICE_GTK_LIBADD_COMMON = \ + libspice-client-glib-2.0.la \ + $(GTK_LIBS) \ + $(CAIRO_LIBS) \ + $(LIBM) \ + $(NULL) + +SPICE_GTK_SOURCES_COMMON = spice-util.c spice-util-priv.h \ + spice-gtk-session.c spice-gtk-session-priv.h spice-widget.c \ + spice-widget-priv.h spice-file-transfer-task.h \ + vncdisplaykeymap.c vncdisplaykeymap.h spice-grabsequence.c \ + spice-grabsequence.h spice-grabsequence-priv.h \ + desktop-integration.c desktop-integration.h \ + usb-device-widget.c $(NULL) spice-widget-cairo.c $(NULL) \ + $(am__append_4) +nodist_SPICE_GTK_SOURCES_COMMON = \ + spice-widget-enums.c \ + spice-marshal.c \ + $(NULL) + +@WITH_GTK_TRUE@EXTRA_libspice_client_gtk_3_0_la_DEPENDENCIES = $(GTK_SYMBOLS_FILE) +@WITH_GTK_TRUE@libspice_client_gtk_3_0_la_LDFLAGS = $(SPICE_GTK_LDFLAGS_COMMON) +@WITH_GTK_TRUE@libspice_client_gtk_3_0_la_LIBADD = $(SPICE_GTK_LIBADD_COMMON) +@WITH_GTK_TRUE@libspice_client_gtk_3_0_la_SOURCES = $(SPICE_GTK_SOURCES_COMMON) +@WITH_GTK_TRUE@nodist_libspice_client_gtk_3_0_la_SOURCES = $(nodist_SPICE_GTK_SOURCES_COMMON) +@WITH_GTK_TRUE@libspice_client_gtkincludedir = $(includedir)/spice-client-gtk-3.0 +@WITH_GTK_TRUE@libspice_client_gtkinclude_HEADERS = \ +@WITH_GTK_TRUE@ spice-client-gtk.h \ +@WITH_GTK_TRUE@ spice-gtk-session.h \ +@WITH_GTK_TRUE@ spice-widget.h \ +@WITH_GTK_TRUE@ spice-grabsequence.h \ +@WITH_GTK_TRUE@ usb-device-widget.h \ +@WITH_GTK_TRUE@ $(NULL) + +@WITH_GTK_TRUE@nodist_libspice_client_gtkinclude_HEADERS = \ +@WITH_GTK_TRUE@ spice-widget-enums.h \ +@WITH_GTK_TRUE@ $(NULL) + +EXTRA_libspice_client_glib_2_0_la_DEPENDENCIES = $(GLIB_SYMBOLS_FILE) +libspice_client_glib_2_0_la_LDFLAGS = \ + -version-info 13:0:5 \ + -no-undefined \ + $(GLIB_SYMBOLS_LDFLAGS) \ + $(NULL) + +libspice_client_glib_2_0_la_LIBADD = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/spice-common/common/libspice-common-client.la \ + $(GLIB2_LIBS) $(SOUP_LIBS) $(GIO_LIBS) $(GOBJECT2_LIBS) \ + $(JPEG_LIBS) $(Z_LIBS) $(LZ4_LIBS) $(PIXMAN_LIBS) $(SSL_LIBS) \ + $(PULSE_LIBS) $(GSTAUDIO_LIBS) $(GSTVIDEO_LIBS) $(SASL_LIBS) \ + $(SMARTCARD_LIBS) $(USBREDIR_LIBS) $(GUDEV_LIBS) \ + $(PHODAV_LIBS) $(NULL) $(am__append_14) $(am__append_16) +@WITH_POLKIT_FALSE@USB_ACL_HELPER_SRCS = +@WITH_POLKIT_TRUE@USB_ACL_HELPER_SRCS = \ +@WITH_POLKIT_TRUE@ usb-acl-helper.c \ +@WITH_POLKIT_TRUE@ usb-acl-helper.h \ +@WITH_POLKIT_TRUE@ $(NULL) + +libspice_client_glib_2_0_la_SOURCES = bio-gio.c bio-gio.h \ + spice-audio.c spice-audio-priv.h spice-common.h spice-util.c \ + spice-util-priv.h spice-option.h spice-option.c spice-client.c \ + spice-session.c spice-session-priv.h spice-channel.c \ + spice-channel-cache.h spice-channel-priv.h coroutine.h \ + gio-coroutine.c gio-coroutine.h channel-base.c \ + channel-webdav.c channel-cursor.c channel-display.c \ + channel-display-priv.h channel-inputs.c channel-main.c \ + channel-playback.c channel-playback-priv.h channel-port.c \ + channel-record.c channel-smartcard.c channel-usbredir.c \ + channel-usbredir-priv.h smartcard-manager.c \ + smartcard-manager-priv.h spice-uri.c spice-uri-priv.h \ + usb-device-manager.c usb-device-manager-priv.h usbutil.c \ + usbutil.h $(USB_ACL_HELPER_SRCS) vmcstream.c vmcstream.h \ + wocky-http-proxy.c wocky-http-proxy.h decode.h decode-glz.c \ + decode-jpeg.c decode-zlib.c client_sw_canvas.c \ + client_sw_canvas.h $(NULL) $(am__append_6) $(am__append_7) \ + $(am__append_8) $(am__append_9) $(am__append_10) \ + $(am__append_11) $(am__append_12) $(am__append_13) \ + $(am__append_15) +nodist_libspice_client_glib_2_0_la_SOURCES = \ + spice-glib-enums.c \ + spice-marshal.c \ + spice-marshal.h \ + $(NULL) + +libspice_client_glibincludedir = $(includedir)/spice-client-glib-2.0 +libspice_client_glibinclude_HEADERS = \ + spice-audio.h \ + spice-client.h \ + spice-uri.h \ + spice-types.h \ + spice-session.h \ + spice-channel.h \ + spice-util.h \ + spice-option.h \ + spice-version.h \ + channel-cursor.h \ + channel-display.h \ + channel-inputs.h \ + channel-main.h \ + channel-playback.h \ + channel-port.h \ + channel-record.h \ + channel-smartcard.h \ + channel-usbredir.h \ + channel-webdav.h \ + usb-device-manager.h \ + smartcard-manager.h \ + spice-file-transfer-task.h \ + $(NULL) + +nodist_libspice_client_glibinclude_HEADERS = \ + spice-glib-enums.h \ + $(NULL) + + +# file for API compatibility, but we don't want warning during our compilation +dist_libspice_client_glibinclude_DATA = \ + spice-channel-enums.h \ + $(NULL) + +WIN_USB_FILES = \ + win-usb-dev.h \ + win-usb-dev.c \ + win-usb-clerk.h \ + win-usb-driver-install.h \ + win-usb-driver-install.c \ + usbdk_api.h \ + usbdk_api.c \ + $(NULL) + +spicy_SOURCES = \ + spicy.c \ + spicy-connect.h \ + spicy-connect.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_LDADD = \ + libspice-client-gtk-3.0.la \ + libspice-client-glib-2.0.la \ + $(GTHREAD_LIBS) \ + $(GTK_LIBS) \ + $(LIBM) \ + $(NULL) + +spicy_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(GTHREAD_CFLAGS) \ + -DSPICE_DISABLE_DEPRECATED \ + $(NULL) + +@WITH_POLKIT_TRUE@spice_client_glib_usb_acl_helper_SOURCES = \ +@WITH_POLKIT_TRUE@ spice-client-glib-usb-acl-helper.c \ +@WITH_POLKIT_TRUE@ $(NULL) + +@WITH_POLKIT_TRUE@spice_client_glib_usb_acl_helper_LDADD = \ +@WITH_POLKIT_TRUE@ $(GLIB2_LIBS) \ +@WITH_POLKIT_TRUE@ $(GIO_LIBS) \ +@WITH_POLKIT_TRUE@ $(POLKIT_LIBS) \ +@WITH_POLKIT_TRUE@ $(ACL_LIBS) \ +@WITH_POLKIT_TRUE@ $(PIE_LDFLAGS) \ +@WITH_POLKIT_TRUE@ $(NULL) + +@WITH_POLKIT_TRUE@spice_client_glib_usb_acl_helper_CPPFLAGS = \ +@WITH_POLKIT_TRUE@ $(SPICE_CFLAGS) \ +@WITH_POLKIT_TRUE@ $(GLIB2_CFLAGS) \ +@WITH_POLKIT_TRUE@ $(GIO_CFLAGS) \ +@WITH_POLKIT_TRUE@ $(POLKIT_CFLAGS) \ +@WITH_POLKIT_TRUE@ $(PIE_CFLAGS) \ +@WITH_POLKIT_TRUE@ $(NULL) + +spicy_screenshot_SOURCES = \ + spicy-screenshot.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_screenshot_LDADD = \ + libspice-client-glib-2.0.la \ + $(GOBJECT2_LIBS) \ + $(NULL) + +spicy_stats_SOURCES = \ + spicy-stats.c \ + spice-cmdline.h \ + spice-cmdline.c \ + $(NULL) + +spicy_stats_LDADD = \ + libspice-client-glib-2.0.la \ + $(GOBJECT2_LIBS) \ + $(NULL) + +@G_IR_SCANNER_SYMBOL_PREFIX_FALSE@PREFIX_ARGS = --strip-prefix=Spice +@G_IR_SCANNER_SYMBOL_PREFIX_TRUE@PREFIX_ARGS = --symbol-prefix=spice --identifier-prefix=Spice +INTROSPECTION_GIRS = $(am__append_17) $(am__append_18) +INTROSPECTION_SCANNER_ARGS = --warn-all --accept-unprefixed --add-include-path=$(builddir) $(PREFIX_ARGS) +INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) +@HAVE_INTROSPECTION_TRUE@glib_introspection_files = \ +@HAVE_INTROSPECTION_TRUE@ $(libspice_client_glibinclude_HEADERS) \ +@HAVE_INTROSPECTION_TRUE@ $(nodist_libspice_client_glibinclude_HEADERS) \ +@HAVE_INTROSPECTION_TRUE@ spice-audio.c \ +@HAVE_INTROSPECTION_TRUE@ spice-client.c \ +@HAVE_INTROSPECTION_TRUE@ spice-session.c \ +@HAVE_INTROSPECTION_TRUE@ spice-channel.c \ +@HAVE_INTROSPECTION_TRUE@ spice-glib-enums.c \ +@HAVE_INTROSPECTION_TRUE@ spice-option.c \ +@HAVE_INTROSPECTION_TRUE@ spice-util.c \ +@HAVE_INTROSPECTION_TRUE@ channel-webdav.c \ +@HAVE_INTROSPECTION_TRUE@ channel-cursor.c \ +@HAVE_INTROSPECTION_TRUE@ channel-display.c \ +@HAVE_INTROSPECTION_TRUE@ channel-inputs.c \ +@HAVE_INTROSPECTION_TRUE@ channel-main.c \ +@HAVE_INTROSPECTION_TRUE@ channel-playback.c \ +@HAVE_INTROSPECTION_TRUE@ channel-port.c \ +@HAVE_INTROSPECTION_TRUE@ channel-record.c \ +@HAVE_INTROSPECTION_TRUE@ channel-smartcard.c \ +@HAVE_INTROSPECTION_TRUE@ channel-usbredir.c \ +@HAVE_INTROSPECTION_TRUE@ smartcard-manager.c \ +@HAVE_INTROSPECTION_TRUE@ usb-device-manager.c \ +@HAVE_INTROSPECTION_TRUE@ $(NULL) + +@HAVE_INTROSPECTION_TRUE@gtk_introspection_files = \ +@HAVE_INTROSPECTION_TRUE@ $(libspice_client_gtkinclude_HEADERS) \ +@HAVE_INTROSPECTION_TRUE@ $(nodist_libspice_client_gtkinclude_HEADERS) \ +@HAVE_INTROSPECTION_TRUE@ spice-gtk-session.c \ +@HAVE_INTROSPECTION_TRUE@ spice-widget.c \ +@HAVE_INTROSPECTION_TRUE@ spice-grabsequence.c \ +@HAVE_INTROSPECTION_TRUE@ usb-device-widget.c \ +@HAVE_INTROSPECTION_TRUE@ $(NULL) + +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_INCLUDES = GObject-2.0 Gio-2.0 +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS) +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_LIBS = libspice-client-glib-2.0.la +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_FILES = $(glib_introspection_files) +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_EXPORT_PACKAGES = spice-client-glib-2.0 +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib_2_0_gir_SCANNERFLAGS = --c-include="spice-client.h" +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 SpiceClientGLib-2.0 +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS) +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_LIBS = libspice-client-gtk-3.0.la libspice-client-glib-2.0.la +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_FILES = $(gtk_introspection_files) +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_EXPORT_PACKAGES = spice-client-gtk-3.0 +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk_3_0_gir_SCANNERFLAGS = --c-include="spice-widget.h" +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS) +@HAVE_INTROSPECTION_TRUE@typelibsdir = $(libdir)/girepository-1.0 +@HAVE_INTROSPECTION_TRUE@typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +spice-version.h: $(top_builddir)/config.status $(srcdir)/spice-version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libspice-client-glib-2.0.la: $(libspice_client_glib_2_0_la_OBJECTS) $(libspice_client_glib_2_0_la_DEPENDENCIES) $(EXTRA_libspice_client_glib_2_0_la_DEPENDENCIES) + $(AM_V_CCLD)$(libspice_client_glib_2_0_la_LINK) -rpath $(libdir) $(libspice_client_glib_2_0_la_OBJECTS) $(libspice_client_glib_2_0_la_LIBADD) $(LIBS) + +libspice-client-gtk-3.0.la: $(libspice_client_gtk_3_0_la_OBJECTS) $(libspice_client_gtk_3_0_la_DEPENDENCIES) $(EXTRA_libspice_client_gtk_3_0_la_DEPENDENCIES) + $(AM_V_CCLD)$(libspice_client_gtk_3_0_la_LINK) $(am_libspice_client_gtk_3_0_la_rpath) $(libspice_client_gtk_3_0_la_OBJECTS) $(libspice_client_gtk_3_0_la_LIBADD) $(LIBS) +install-aclPROGRAMS: $(acl_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(acl_PROGRAMS)'; test -n "$(acldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(acldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(acldir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(acldir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(acldir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-aclPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(acl_PROGRAMS)'; test -n "$(acldir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(acldir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(acldir)" && rm -f $$files + +clean-aclPROGRAMS: + @list='$(acl_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +spice-client-glib-usb-acl-helper$(EXEEXT): $(spice_client_glib_usb_acl_helper_OBJECTS) $(spice_client_glib_usb_acl_helper_DEPENDENCIES) $(EXTRA_spice_client_glib_usb_acl_helper_DEPENDENCIES) + @rm -f spice-client-glib-usb-acl-helper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(spice_client_glib_usb_acl_helper_OBJECTS) $(spice_client_glib_usb_acl_helper_LDADD) $(LIBS) + +spicy$(EXEEXT): $(spicy_OBJECTS) $(spicy_DEPENDENCIES) $(EXTRA_spicy_DEPENDENCIES) + @rm -f spicy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(spicy_OBJECTS) $(spicy_LDADD) $(LIBS) + +spicy-screenshot$(EXEEXT): $(spicy_screenshot_OBJECTS) $(spicy_screenshot_DEPENDENCIES) $(EXTRA_spicy_screenshot_DEPENDENCIES) + @rm -f spicy-screenshot$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(spicy_screenshot_OBJECTS) $(spicy_screenshot_LDADD) $(LIBS) + +spicy-stats$(EXEEXT): $(spicy_stats_OBJECTS) $(spicy_stats_DEPENDENCIES) $(EXTRA_spicy_stats_DEPENDENCIES) + @rm -f spicy-stats$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(spicy_stats_OBJECTS) $(spicy_stats_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bio-gio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-base.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-cursor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-display-gst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-display-mjpeg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-display.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-inputs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-main.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-playback.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-port.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-record.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-smartcard.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-usbredir.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel-webdav.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_sw_canvas.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/continuation.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coroutine_gthread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coroutine_ucontext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coroutine_winfibers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-glz.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-jpeg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-zlib.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/desktop-integration.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gio-coroutine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/giopipe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smartcard-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-audio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-channel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-glib-enums.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-grabsequence.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-gstaudio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-gtk-session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-marshal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-option.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-pulse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-uri.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-widget-cairo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-widget-egl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-widget-enums.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-widget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spicy-screenshot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spicy-spice-cmdline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spicy-spicy-connect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spicy-spicy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spicy-stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb-acl-helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb-device-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb-device-widget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usbdk_api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usbutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmcstream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vncdisplaykeymap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win-usb-dev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win-usb-driver-install.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-http-proxy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.o: spice-client-glib-usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spice_client_glib_usb_acl_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.o -MD -MP -MF $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Tpo -c -o spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.o `test -f 'spice-client-glib-usb-acl-helper.c' || echo '$(srcdir)/'`spice-client-glib-usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Tpo $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spice-client-glib-usb-acl-helper.c' object='spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spice_client_glib_usb_acl_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.o `test -f 'spice-client-glib-usb-acl-helper.c' || echo '$(srcdir)/'`spice-client-glib-usb-acl-helper.c + +spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.obj: spice-client-glib-usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spice_client_glib_usb_acl_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.obj -MD -MP -MF $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Tpo -c -o spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.obj `if test -f 'spice-client-glib-usb-acl-helper.c'; then $(CYGPATH_W) 'spice-client-glib-usb-acl-helper.c'; else $(CYGPATH_W) '$(srcdir)/spice-client-glib-usb-acl-helper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Tpo $(DEPDIR)/spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spice-client-glib-usb-acl-helper.c' object='spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spice_client_glib_usb_acl_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spice_client_glib_usb_acl_helper-spice-client-glib-usb-acl-helper.obj `if test -f 'spice-client-glib-usb-acl-helper.c'; then $(CYGPATH_W) 'spice-client-glib-usb-acl-helper.c'; else $(CYGPATH_W) '$(srcdir)/spice-client-glib-usb-acl-helper.c'; fi` + +spicy-spicy.o: spicy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spicy.o -MD -MP -MF $(DEPDIR)/spicy-spicy.Tpo -c -o spicy-spicy.o `test -f 'spicy.c' || echo '$(srcdir)/'`spicy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spicy.Tpo $(DEPDIR)/spicy-spicy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spicy.c' object='spicy-spicy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spicy.o `test -f 'spicy.c' || echo '$(srcdir)/'`spicy.c + +spicy-spicy.obj: spicy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spicy.obj -MD -MP -MF $(DEPDIR)/spicy-spicy.Tpo -c -o spicy-spicy.obj `if test -f 'spicy.c'; then $(CYGPATH_W) 'spicy.c'; else $(CYGPATH_W) '$(srcdir)/spicy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spicy.Tpo $(DEPDIR)/spicy-spicy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spicy.c' object='spicy-spicy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spicy.obj `if test -f 'spicy.c'; then $(CYGPATH_W) 'spicy.c'; else $(CYGPATH_W) '$(srcdir)/spicy.c'; fi` + +spicy-spicy-connect.o: spicy-connect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spicy-connect.o -MD -MP -MF $(DEPDIR)/spicy-spicy-connect.Tpo -c -o spicy-spicy-connect.o `test -f 'spicy-connect.c' || echo '$(srcdir)/'`spicy-connect.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spicy-connect.Tpo $(DEPDIR)/spicy-spicy-connect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spicy-connect.c' object='spicy-spicy-connect.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spicy-connect.o `test -f 'spicy-connect.c' || echo '$(srcdir)/'`spicy-connect.c + +spicy-spicy-connect.obj: spicy-connect.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spicy-connect.obj -MD -MP -MF $(DEPDIR)/spicy-spicy-connect.Tpo -c -o spicy-spicy-connect.obj `if test -f 'spicy-connect.c'; then $(CYGPATH_W) 'spicy-connect.c'; else $(CYGPATH_W) '$(srcdir)/spicy-connect.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spicy-connect.Tpo $(DEPDIR)/spicy-spicy-connect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spicy-connect.c' object='spicy-spicy-connect.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spicy-connect.obj `if test -f 'spicy-connect.c'; then $(CYGPATH_W) 'spicy-connect.c'; else $(CYGPATH_W) '$(srcdir)/spicy-connect.c'; fi` + +spicy-spice-cmdline.o: spice-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spice-cmdline.o -MD -MP -MF $(DEPDIR)/spicy-spice-cmdline.Tpo -c -o spicy-spice-cmdline.o `test -f 'spice-cmdline.c' || echo '$(srcdir)/'`spice-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spice-cmdline.Tpo $(DEPDIR)/spicy-spice-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spice-cmdline.c' object='spicy-spice-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spice-cmdline.o `test -f 'spice-cmdline.c' || echo '$(srcdir)/'`spice-cmdline.c + +spicy-spice-cmdline.obj: spice-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spicy-spice-cmdline.obj -MD -MP -MF $(DEPDIR)/spicy-spice-cmdline.Tpo -c -o spicy-spice-cmdline.obj `if test -f 'spice-cmdline.c'; then $(CYGPATH_W) 'spice-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/spice-cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spicy-spice-cmdline.Tpo $(DEPDIR)/spicy-spice-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spice-cmdline.c' object='spicy-spice-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spicy_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spicy-spice-cmdline.obj `if test -f 'spice-cmdline.c'; then $(CYGPATH_W) 'spice-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/spice-cmdline.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_libspice_client_glibincludeDATA: $(dist_libspice_client_glibinclude_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_libspice_client_glibinclude_DATA)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_client_glibincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(libspice_client_glibincludedir)" || exit $$?; \ + done + +uninstall-dist_libspice_client_glibincludeDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_libspice_client_glibinclude_DATA)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_client_glibincludedir)'; $(am__uninstall_files_from_dir) +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-typelibsDATA: $(typelibs_DATA) + @$(NORMAL_INSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibsdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibsdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibsdir)" || exit $$?; \ + done + +uninstall-typelibsDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelibs_DATA)'; test -n "$(typelibsdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibsdir)'; $(am__uninstall_files_from_dir) +install-libspice_client_glibincludeHEADERS: $(libspice_client_glibinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libspice_client_glibinclude_HEADERS)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_client_glibincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libspice_client_glibincludedir)" || exit $$?; \ + done + +uninstall-libspice_client_glibincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libspice_client_glibinclude_HEADERS)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_client_glibincludedir)'; $(am__uninstall_files_from_dir) +install-libspice_client_gtkincludeHEADERS: $(libspice_client_gtkinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libspice_client_gtkinclude_HEADERS)'; test -n "$(libspice_client_gtkincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_client_gtkincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_client_gtkincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libspice_client_gtkincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libspice_client_gtkincludedir)" || exit $$?; \ + done + +uninstall-libspice_client_gtkincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libspice_client_gtkinclude_HEADERS)'; test -n "$(libspice_client_gtkincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_client_gtkincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_libspice_client_glibincludeHEADERS: $(nodist_libspice_client_glibinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libspice_client_glibinclude_HEADERS)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_client_glibincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libspice_client_glibincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libspice_client_glibincludedir)" || exit $$?; \ + done + +uninstall-nodist_libspice_client_glibincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libspice_client_glibinclude_HEADERS)'; test -n "$(libspice_client_glibincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_client_glibincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_libspice_client_gtkincludeHEADERS: $(nodist_libspice_client_gtkinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_libspice_client_gtkinclude_HEADERS)'; test -n "$(libspice_client_gtkincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_client_gtkincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_client_gtkincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libspice_client_gtkincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libspice_client_gtkincludedir)" || exit $$?; \ + done + +uninstall-nodist_libspice_client_gtkincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_libspice_client_gtkinclude_HEADERS)'; test -n "$(libspice_client_gtkincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_client_gtkincludedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(acldir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libspice_client_glibincludedir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibsdir)" "$(DESTDIR)$(libspice_client_glibincludedir)" "$(DESTDIR)$(libspice_client_gtkincludedir)" "$(DESTDIR)$(libspice_client_glibincludedir)" "$(DESTDIR)$(libspice_client_gtkincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +@WITH_POLKIT_FALSE@install-data-hook: +clean: clean-recursive + +clean-am: clean-aclPROGRAMS clean-binPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-aclPROGRAMS \ + install-dist_libspice_client_glibincludeDATA install-girDATA \ + install-libspice_client_glibincludeHEADERS \ + install-libspice_client_gtkincludeHEADERS \ + install-nodist_libspice_client_glibincludeHEADERS \ + install-nodist_libspice_client_gtkincludeHEADERS \ + install-typelibsDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -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-aclPROGRAMS uninstall-binPROGRAMS \ + uninstall-dist_libspice_client_glibincludeDATA \ + uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libspice_client_glibincludeHEADERS \ + uninstall-libspice_client_gtkincludeHEADERS \ + uninstall-nodist_libspice_client_glibincludeHEADERS \ + uninstall-nodist_libspice_client_gtkincludeHEADERS \ + uninstall-typelibsDATA + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-data-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-aclPROGRAMS clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-aclPROGRAMS install-am \ + install-binPROGRAMS install-data install-data-am \ + install-data-hook install-dist_libspice_client_glibincludeDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-girDATA install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES \ + install-libspice_client_glibincludeHEADERS \ + install-libspice_client_gtkincludeHEADERS install-man \ + install-nodist_libspice_client_glibincludeHEADERS \ + install-nodist_libspice_client_gtkincludeHEADERS install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + install-typelibsDATA installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-aclPROGRAMS uninstall-am uninstall-binPROGRAMS \ + uninstall-dist_libspice_client_glibincludeDATA \ + uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libspice_client_glibincludeHEADERS \ + uninstall-libspice_client_gtkincludeHEADERS \ + uninstall-nodist_libspice_client_glibincludeHEADERS \ + uninstall-nodist_libspice_client_gtkincludeHEADERS \ + uninstall-typelibsDATA + +.PRECIOUS: Makefile + + +@WITH_POLKIT_TRUE@install-data-hook: +@WITH_POLKIT_TRUE@ -chown root $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper +@WITH_POLKIT_TRUE@ -chmod u+s $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper + +$(libspice_client_glib_2_0_la_SOURCES): spice-glib-enums.h spice-marshal.h + +@WITH_GTK_TRUE@$(libspice_client_gtk_3_0_la_SOURCES): spice-glib-enums.h spice-widget-enums.h + +spice-marshal.c: spice-marshal.h +spice-glib-enums.c: spice-glib-enums.h +spice-widget-enums.c: spice-widget-enums.h + +spice-marshal.c: spice-marshal.txt + $(AM_V_GEN)echo "#include \"config.h\"" > $@ && \ + echo "#include \"spice-marshal.h\"" > $@ && \ + glib-genmarshal --body $< >> $@ || (rm -f $@ && exit 1) + +spice-marshal.h: spice-marshal.txt + $(AM_V_GEN)glib-genmarshal --header $< > $@ || (rm -f $@ && exit 1) + +spice-glib-enums.c: spice-channel.h channel-inputs.h spice-session.h + $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \ + --fhead "#include \n" \ + --fhead "#include \"spice-glib-enums.h\"\n\n" \ + --fprod "\n#include \"spice-session.h\"\n" \ + --fprod "\n#include \"spice-channel.h\"\n" \ + --fprod "\n#include \"channel-inputs.h\"\n" \ + --vhead "static const G@Type@Value _@enum_name@_values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n};\n\n" \ + --vtail "GType\n@enum_name@_get_type (void)\n{\n" \ + --vtail " static GType type = 0;\n" \ + --vtail " static volatile gsize type_volatile = 0;\n\n" \ + --vtail " if (g_once_init_enter(&type_volatile)) {\n" \ + --vtail " type = g_@type@_register_static (\"@EnumName@\", _@enum_name@_values);\n" \ + --vtail " g_once_init_leave(&type_volatile, type);\n" \ + --vtail " }\n\n" \ + --vtail " return type;\n}\n\n" \ + $^ > $@ + +spice-glib-enums.h: spice-channel.h channel-inputs.h spice-session.h + $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_GLIB_ENUMS_H\n" \ + --fhead "#define SPICE_GLIB_ENUMS_H\n\n" \ + --fhead "G_BEGIN_DECLS\n\n" \ + --ftail "G_END_DECLS\n\n" \ + --ftail "#endif /* SPICE_CHANNEL_ENUMS_H */\n" \ + --eprod "#define SPICE_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \ + --eprod "GType @enum_name@_get_type (void);\n" \ + $^ > $@ + +spice-widget-enums.c: spice-widget.h + $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \ + --fhead "#include \n" \ + --fhead "#include \"spice-widget-enums.h\"\n\n" \ + --fprod "\n#include \"spice-widget.h\"\n" \ + --vhead "static const G@Type@Value _@enum_name@_values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n};\n\n" \ + --vtail "GType\n@enum_name@_get_type (void)\n{\n" \ + --vtail " static GType type = 0;\n" \ + --vtail " static volatile gsize type_volatile = 0;\n\n" \ + --vtail " if (g_once_init_enter(&type_volatile)) {\n" \ + --vtail " type = g_@type@_register_static (\"@EnumName@\", _@enum_name@_values);\n" \ + --vtail " g_once_init_leave(&type_volatile, type);\n" \ + --vtail " }\n\n" \ + --vtail " return type;\n}\n\n" \ + $< > $@ + +spice-widget-enums.h: spice-widget.h + $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_WIDGET_ENUMS_H\n" \ + --fhead "#define SPICE_WIDGET_ENUMS_H\n\n" \ + --fhead "G_BEGIN_DECLS\n\n" \ + --ftail "G_END_DECLS\n\n" \ + --ftail "#endif /* SPICE_WIDGET_ENUMS_H */\n" \ + --eprod "#define SPICE_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n" \ + --eprod "GType @enum_name@_get_type (void);\n" \ + $< > $@ + +vncdisplaykeymap.c: $(KEYMAPS) + +$(KEYMAPS): $(KEYMAP_GEN) keymaps.csv + +# Note despite being autogenerated these are not part of CLEANFILES, they +# are actually a part of EXTRA_DIST to avoid the need for perl(Text::CSV) by +# end users +vncdisplaykeymap_xorgevdev2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgevdev xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgkbd2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgkbd xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgxquartz2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxquartz xtkbd > $@ || rm $@ + +vncdisplaykeymap_xorgxwin2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxwin xtkbd > $@ || rm $@ + +vncdisplaykeymap_osx2xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv osx xtkbd > $@ || rm $@ + +vncdisplaykeymap_win322xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv win32 xtkbd > $@ || rm $@ + +vncdisplaykeymap_x112xtkbd.c: + $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv x11 xtkbd > $@ || rm $@ + +-include $(INTROSPECTION_MAKEFILE) + +@HAVE_INTROSPECTION_TRUE@SpiceClientGLib-2.0.gir: libspice-client-glib-2.0.la + +@HAVE_INTROSPECTION_TRUE@@WITH_GTK_TRUE@SpiceClientGtk-3.0.gir: libspice-client-gtk-3.0.la SpiceClientGLib-2.0.gir + +update-map-file: $(libspice_client_gtkinclude_HEADERS) $(nodist_libspice_client_gtkinclude_HEADERS) $(libspice_client_glibinclude_HEADERS) $(nodist_libspice_client_glibinclude_HEADERS) + ( echo "SPICEGTK_1 {" ; \ + echo "global:" ; \ + ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 ";" }' | sort ; \ + echo "local:" ; \ + echo "*;" ; \ + echo "};" ) > $(srcdir)/map-file + +update-glib-sym-file: $(libspice_client_glibinclude_HEADERS) $(nodist_libspice_client_glibinclude_HEADERS) + ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }' | sort ; \ + ) > $(srcdir)/spice-glib-sym-file + +update-gtk-sym-file: $(libspice_client_gtkinclude_HEADERS) $(nodist_libspice_client_gtkinclude_HEADERS) + ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }' | sort ; \ + ) > $(srcdir)/spice-gtk-sym-file + +update-symbol-files: update-map-file update-glib-sym-file update-gtk-sym-file + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/bio-gio.c b/src/bio-gio.c new file mode 100644 index 0000000..b310c97 --- /dev/null +++ b/src/bio-gio.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#include "spice-util.h" +#include "bio-gio.h" + +typedef struct bio_gsocket_method { + BIO_METHOD method; + GIOStream *stream; +} bio_gsocket_method; + +#define BIO_GET_GSOCKET(bio) (((bio_gsocket_method*)bio->method)->gsocket) +#define BIO_GET_ISTREAM(bio) (g_io_stream_get_input_stream(((bio_gsocket_method*)bio->method)->stream)) +#define BIO_GET_OSTREAM(bio) (g_io_stream_get_output_stream(((bio_gsocket_method*)bio->method)->stream)) + +static int bio_gio_write(BIO *bio, const char *in, int inl) +{ + gssize ret; + GError *error = NULL; + + ret = g_pollable_output_stream_write_nonblocking(G_POLLABLE_OUTPUT_STREAM(BIO_GET_OSTREAM(bio)), + in, inl, NULL, &error); + BIO_clear_retry_flags(bio); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + BIO_set_retry_write(bio); + if (error != NULL) { + g_warning("%s", error->message); + g_clear_error(&error); + } + + return ret; +} + +static int bio_gio_read(BIO *bio, char *out, int outl) +{ + gssize ret; + GError *error = NULL; + + ret = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(BIO_GET_ISTREAM(bio)), + out, outl, NULL, &error); + BIO_clear_retry_flags(bio); + + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + BIO_set_retry_read(bio); + else if (error != NULL) + g_warning("%s", error->message); + + g_clear_error(&error); + + return ret; +} + +static int bio_gio_destroy(BIO *bio) +{ + if (bio == NULL || bio->method == NULL) + return 0; + + SPICE_DEBUG("bio gsocket destroy"); + g_clear_pointer(&bio->method, g_free); + + return 1; +} + +static int bio_gio_puts(BIO *bio, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = bio_gio_write(bio, str, n); + + return ret; +} + +G_GNUC_INTERNAL +BIO* bio_new_giostream(GIOStream *stream) +{ + // TODO: make an actual new BIO type, or just switch to GTls already... + BIO *bio = BIO_new_socket(-1, BIO_NOCLOSE); + + bio_gsocket_method *bio_method = g_new(bio_gsocket_method, 1); + bio_method->method = *bio->method; + bio_method->stream = stream; + + bio->method->destroy(bio); + bio->method = (BIO_METHOD*)bio_method; + + bio->method->bwrite = bio_gio_write; + bio->method->bread = bio_gio_read; + bio->method->bputs = bio_gio_puts; + bio->method->destroy = bio_gio_destroy; + + return bio; +} diff --git a/src/bio-gio.h b/src/bio-gio.h new file mode 100644 index 0000000..31fd369 --- /dev/null +++ b/src/bio-gio.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef BIO_GIO_H_ +# define BIO_GIO_H_ + +#include +#include + +G_BEGIN_DECLS + +BIO* bio_new_giostream(GIOStream *stream); + +G_END_DECLS + +#endif /* !BIO_GIO_H_ */ diff --git a/src/channel-base.c b/src/channel-base.c new file mode 100644 index 0000000..004dba9 --- /dev/null +++ b/src/channel-base.c @@ -0,0 +1,283 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-session-priv.h" +#include "spice-channel-priv.h" + +/* coroutine context */ +static void +spice_channel_handle_set_ack(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgSetAck* ack = spice_msg_in_parsed(in); + SpiceMsgOut *out = spice_msg_out_new(channel, SPICE_MSGC_ACK_SYNC); + SpiceMsgcAckSync sync = { + .generation = ack->generation, + }; + + c->message_ack_window = c->message_ack_count = ack->window; + c->marshallers->msgc_ack_sync(out->marshaller, &sync); + spice_msg_out_send_internal(out); +} + +/* coroutine context */ +static void +spice_channel_handle_ping(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgPing *ping = spice_msg_in_parsed(in); + SpiceMsgOut *pong = spice_msg_out_new(channel, SPICE_MSGC_PONG); + + c->marshallers->msgc_pong(pong->marshaller, ping); + spice_msg_out_send_internal(pong); +} + +/* coroutine context */ +static void +spice_channel_handle_notify(SpiceChannel *channel, SpiceMsgIn *in) +{ + static const char* severity_strings[] = {"info", "warn", "error"}; + static const char* visibility_strings[] = {"!", "!!", "!!!"}; + + SpiceMsgNotify *notify = spice_msg_in_parsed(in); + const char *severity = "?"; + const char *visibility = "?"; + const char *message_str = NULL; + + if (notify->severity <= SPICE_NOTIFY_SEVERITY_ERROR) { + severity = severity_strings[notify->severity]; + } + if (notify->visibilty <= SPICE_NOTIFY_VISIBILITY_HIGH) { + visibility = visibility_strings[notify->visibilty]; + } + + if (notify->message_len && + notify->message_len <= in->dpos - sizeof(*notify)) { + message_str = (char*)notify->message; + } + + CHANNEL_DEBUG(channel, "%s -- %s%s #%u%s%.*s", __FUNCTION__, + severity, visibility, notify->what, + message_str ? ": " : "", (int)notify->message_len, + message_str ? message_str : ""); +} + +/* coroutine context */ +static void +spice_channel_handle_disconnect(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisconnect *disconnect = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "%s: ts: %" PRIu64", reason: %u", __FUNCTION__, + disconnect->time_stamp, disconnect->reason); +} + +typedef struct WaitForChannelData +{ + SpiceWaitForChannel *wait; + SpiceChannel *channel; +} WaitForChannelData; + +/* coroutine and main context */ +static gboolean wait_for_channel(gpointer data) +{ + WaitForChannelData *wfc = data; + SpiceChannelPrivate *c = wfc->channel->priv; + SpiceChannel *wait_channel; + + wait_channel = spice_session_lookup_channel(c->session, wfc->wait->channel_id, wfc->wait->channel_type); + g_return_val_if_fail(wait_channel != NULL, TRUE); + + if (wait_channel->priv->last_message_serial >= wfc->wait->message_serial) + return TRUE; + + return FALSE; +} + +/* coroutine context */ +G_GNUC_INTERNAL +void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgWaitForChannels *wfc = spice_msg_in_parsed(in); + int i; + + for (i = 0; i < wfc->wait_count; ++i) { + WaitForChannelData data = { + .wait = wfc->wait_list + i, + .channel = channel + }; + + CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 " (%d/%d)", data.wait->message_serial, i + 1, wfc->wait_count); + if (g_coroutine_condition_wait(&c->coroutine, wait_for_channel, &data)) + CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 ", done", data.wait->message_serial); + else + CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 ", cancelled", data.wait->message_serial); + } +} + +static void +get_msg_handler(SpiceChannel *channel, SpiceMsgIn *in, gpointer data) +{ + SpiceMsgIn **msg = data; + + g_return_if_fail(msg != NULL); + g_return_if_fail(*msg == NULL); + + spice_msg_in_ref(in); + *msg = in; +} + +/* coroutine context */ +static void +spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgOut *out; + SpiceMsgIn *data = NULL; + SpiceMsgMigrate *mig = spice_msg_in_parsed(in); + SpiceChannelPrivate *c = channel->priv; + + CHANNEL_DEBUG(channel, "%s: flags %u", __FUNCTION__, mig->flags); + if (mig->flags & SPICE_MIGRATE_NEED_FLUSH) { + /* if peer version > 1: pushing the mark msg before all other messgages and sending it, + * and only it */ + if (c->peer_hdr.major_version == 1) { + /* iterate_write is blocking and flushing all pending write */ + SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); + } + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_FLUSH_MARK); + spice_msg_out_send_internal(out); + } + if (mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) { + spice_channel_recv_msg(channel, get_msg_handler, &data); + if (!data) { + g_critical("expected SPICE_MSG_MIGRATE_DATA, got empty message"); + goto end; + } else if (spice_header_get_msg_type(data->header, c->use_mini_header) != + SPICE_MSG_MIGRATE_DATA) { + g_critical("expected SPICE_MSG_MIGRATE_DATA, got %d", + spice_header_get_msg_type(data->header, c->use_mini_header)); + goto end; + } + } + + /* swapping channels sockets */ + spice_session_channel_migrate(c->session, channel); + + /* pushing the MIGRATE_DATA before all other pending messages */ + if ((mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) && (data != NULL)) { + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_DATA); + spice_marshaller_add(out->marshaller, data->data, + spice_header_get_msg_size(data->header, c->use_mini_header)); + spice_msg_out_send_internal(out); + } + +end: + if (data) + spice_msg_in_unref(data); +} + + +static void set_handlers(SpiceChannelClassPrivate *klass, + const spice_msg_handler* handlers, const int n) +{ + int i; + + g_array_set_size(klass->handlers, MAX(klass->handlers->len, n)); + for (i = 0; i < n; i++) { + if (handlers[i]) + g_array_index(klass->handlers, spice_msg_handler, i) = handlers[i]; + } +} + +static void spice_channel_add_base_handlers(SpiceChannelClassPrivate *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_SET_ACK ] = spice_channel_handle_set_ack, + [ SPICE_MSG_PING ] = spice_channel_handle_ping, + [ SPICE_MSG_NOTIFY ] = spice_channel_handle_notify, + [ SPICE_MSG_DISCONNECTING ] = spice_channel_handle_disconnect, + [ SPICE_MSG_WAIT_FOR_CHANNELS ] = spice_channel_handle_wait_for_channels, + [ SPICE_MSG_MIGRATE ] = spice_channel_handle_migrate, + }; + + set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +G_GNUC_INTERNAL +void spice_channel_set_handlers(SpiceChannelClass *klass, + const spice_msg_handler* handlers, const int n) +{ + klass->priv = + G_TYPE_CLASS_GET_PRIVATE (klass, spice_channel_get_type (), SpiceChannelClassPrivate); + + g_return_if_fail(klass->priv->handlers == NULL); + klass->priv->handlers = g_array_sized_new(FALSE, TRUE, sizeof(spice_msg_handler), n); + + spice_channel_add_base_handlers(klass->priv); + set_handlers(klass->priv, handlers, n); +} + +static void +vmc_write_free_cb(uint8_t *data, void *user_data) +{ + GTask *task = user_data; + gsize count = GPOINTER_TO_SIZE(g_task_get_task_data(task)); + + g_task_return_int(task, count); + + g_object_unref(task); +} + +G_GNUC_INTERNAL +void spice_vmc_write_async(SpiceChannel *self, + const void *buffer, gsize count, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceMsgOut *msg; + GTask *task; + + task = g_task_new(self, cancellable, callback, user_data); + g_task_set_task_data(task, GSIZE_TO_POINTER(count), NULL); + + msg = spice_msg_out_new(SPICE_CHANNEL(self), SPICE_MSGC_SPICEVMC_DATA); + spice_marshaller_add_ref_full(msg->marshaller, (uint8_t*)buffer, count, + vmc_write_free_cb, task); + spice_msg_out_send(msg); +} + +G_GNUC_INTERNAL +gssize spice_vmc_write_finish(SpiceChannel *self, + GAsyncResult *result, GError **error) +{ + GTask *task; + + g_return_val_if_fail(result != NULL, -1); + + task = G_TASK(result); + + g_return_val_if_fail(g_task_is_valid(task, self), -1); + + return g_task_propagate_int(task, error); +} diff --git a/src/channel-cursor.c b/src/channel-cursor.c new file mode 100644 index 0000000..609243b --- /dev/null +++ b/src/channel-cursor.c @@ -0,0 +1,528 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-channel-priv.h" +#include "spice-channel-cache.h" +#include "spice-marshal.h" + +/** + * SECTION:channel-cursor + * @short_description: update cursor shape and position + * @title: Cursor Channel + * @section_id: + * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client.h + * + * The Spice protocol defines a set of messages for controlling cursor + * shape and position on the remote display area. The cursor changes + * that should be reflected on the display are notified by + * signals. See for example #SpiceCursorChannel::cursor-set + * #SpiceCursorChannel::cursor-move signals. + */ + +#define SPICE_CURSOR_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_CURSOR_CHANNEL, SpiceCursorChannelPrivate)) + +typedef struct display_cursor display_cursor; + +struct display_cursor { + SpiceCursorHeader hdr; + gboolean default_cursor; + int refcount; + guint32 data[]; +}; + +struct _SpiceCursorChannelPrivate { + display_cache *cursors; + gboolean init_done; +}; + +enum { + SPICE_CURSOR_SET, + SPICE_CURSOR_MOVE, + SPICE_CURSOR_HIDE, + SPICE_CURSOR_RESET, + + SPICE_CURSOR_LAST_SIGNAL, +}; + +static guint signals[SPICE_CURSOR_LAST_SIGNAL]; + +static display_cursor * display_cursor_ref(display_cursor *cursor); +static void display_cursor_unref(display_cursor *cursor); +static void channel_set_handlers(SpiceChannelClass *klass); + +G_DEFINE_TYPE(SpiceCursorChannel, spice_cursor_channel, SPICE_TYPE_CHANNEL) + +/* ------------------------------------------------------------------ */ + +static void spice_cursor_channel_init(SpiceCursorChannel *channel) +{ + SpiceCursorChannelPrivate *c; + + c = channel->priv = SPICE_CURSOR_CHANNEL_GET_PRIVATE(channel); + + c->cursors = cache_new((GDestroyNotify)display_cursor_unref); +} + +static void spice_cursor_channel_finalize(GObject *obj) +{ + SpiceCursorChannel *channel = SPICE_CURSOR_CHANNEL(obj); + SpiceCursorChannelPrivate *c = channel->priv; + + g_clear_pointer(&c->cursors, cache_free); + + if (G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize(obj); +} + +/* coroutine context */ +static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + cache_clear(c->cursors); + c->init_done = FALSE; + + SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_cursor_channel_finalize; + channel_class->channel_reset = spice_cursor_channel_reset; + + /** + * SpiceCursorChannel::cursor-set: + * @cursor: the #SpiceCursorChannel that emitted the signal + * @width: width of the shape + * @height: height of the shape + * @hot_x: horizontal offset of the 'hotspot' of the cursor + * @hot_y: vertical offset of the 'hotspot' of the cursor + * @rgba: 32bits shape data, or %NULL if default cursor. It might + * be freed after the signal is emitted, so make sure to copy it + * if you need it later! + * + * The #SpiceCursorChannel::cursor-set signal is emitted to modify + * cursor aspect and position on the display area. + **/ + signals[SPICE_CURSOR_SET] = + g_signal_new("cursor-set", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_set), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT_INT_INT_POINTER, + G_TYPE_NONE, + 5, + G_TYPE_INT, G_TYPE_INT, + G_TYPE_INT, G_TYPE_INT, + G_TYPE_POINTER); + + /** + * SpiceCursorChannel::cursor-move: + * @cursor: the #SpiceCursorChannel that emitted the signal + * @x: x position + * @y: y position + * + * The #SpiceCursorChannel::cursor-move signal is emitted to update + * the cursor position on the display area. + **/ + signals[SPICE_CURSOR_MOVE] = + g_signal_new("cursor-move", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_move), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT, + G_TYPE_NONE, + 2, + G_TYPE_INT, G_TYPE_INT); + + /** + * SpiceCursorChannel::cursor-hide: + * @cursor: the #SpiceCursorChannel that emitted the signal + * + * The #SpiceCursorChannel::cursor-hide signal is emitted to hide + * the cursor/pointer on the display area. + **/ + signals[SPICE_CURSOR_HIDE] = + g_signal_new("cursor-hide", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_hide), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * SpiceCursorChannel::cursor-reset: + * @cursor: the #SpiceCursorChannel that emitted the signal + * + * The #SpiceCursorChannel::cursor-reset signal is emitted to + * reset the cursor to its default context. + **/ + signals[SPICE_CURSOR_RESET] = + g_signal_new("cursor-reset", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_reset), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private(klass, sizeof(SpiceCursorChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* ------------------------------------------------------------------ */ + +#ifdef DEBUG_CURSOR +static void print_cursor(display_cursor *cursor, const guint8 *data) +{ + int x, y, bpl; + const guint8 *xor, *and; + + bpl = (cursor->hdr.width + 7) / 8; + and = data; + xor = and + bpl * cursor->hdr.height; + + printf("data (%d x %d):\n", cursor->hdr.width, cursor->hdr.height); + for (y = 0 ; y < cursor->hdr.height; ++y) { + for (x = 0 ; x < cursor->hdr.width / 8; x++) { + printf("%02X", and[x]); + } + and += bpl; + printf("\n"); + } + printf("xor:\n"); + for (y = 0 ; y < cursor->hdr.height; ++y) { + for (x = 0 ; x < cursor->hdr.width / 8; ++x) { + printf("%02X", xor[x]); + } + xor += bpl; + printf("\n"); + } +} +#endif + +static void mono_cursor(display_cursor *cursor, const guint8 *data) +{ + int bpl = (cursor->hdr.width + 7) / 8; + const guint8 *xor, *and; + guint8 *dest; + dest = (uint8_t *)cursor->data; + +#ifdef DEBUG_CURSOR + print_cursor(cursor, data); +#endif + and = data; + xor = and + bpl * cursor->hdr.height; + spice_mono_edge_highlight(cursor->hdr.width, cursor->hdr.height, + and, xor, dest); +} + +static guint8 get_pix_mask(const guint8 *data, gint offset, gint pix_index) +{ + return data[offset + (pix_index >> 3)] & (0x80 >> (pix_index % 8)); +} + +static guint32 get_pix_hack(gint pix_index, gint width) +{ + return (((pix_index % width) ^ (pix_index / width)) & 1) ? 0xc0303030 : 0x30505050; +} + +static display_cursor * display_cursor_ref(display_cursor *cursor) +{ + g_return_val_if_fail(cursor != NULL, NULL); + g_return_val_if_fail(cursor->refcount > 0, NULL); + + cursor->refcount++; + return cursor; +} + +static void display_cursor_unref(display_cursor *cursor) +{ + g_return_if_fail(cursor != NULL); + g_return_if_fail(cursor->refcount > 0); + + cursor->refcount--; + if (cursor->refcount == 0) + g_free(cursor); +} + +static const char *cursor_type_to_string(int type) +{ + switch (type) { + case SPICE_CURSOR_TYPE_MONO: + return "mono"; + case SPICE_CURSOR_TYPE_ALPHA: + return "alpha"; + case SPICE_CURSOR_TYPE_COLOR32: + return "color32"; + case SPICE_CURSOR_TYPE_COLOR16: + return "color16"; + case SPICE_CURSOR_TYPE_COLOR4: + return "color4"; + } + return "unknown"; +} + +static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + SpiceCursorHeader *hdr = &scursor->header; + display_cursor *cursor; + size_t size; + gint i, pix_mask, pix; + const guint8* data; + guint8 *rgba; + guint8 val; + + CHANNEL_DEBUG(channel, "%s: flags %x, size %u", __FUNCTION__, + scursor->flags, scursor->data_size); + + if (scursor->flags & SPICE_CURSOR_FLAGS_NONE) + return NULL; + + CHANNEL_DEBUG(channel, "%s: type %s(%d), %" PRIx64 ", %dx%d", __FUNCTION__, + cursor_type_to_string(hdr->type), hdr->type, hdr->unique, + hdr->width, hdr->height); + + if (scursor->flags & SPICE_CURSOR_FLAGS_FROM_CACHE) { + cursor = cache_find(c->cursors, hdr->unique); + g_return_val_if_fail(cursor != NULL, NULL); + return display_cursor_ref(cursor); + } + + g_return_val_if_fail(scursor->data_size != 0, NULL); + + size = 4u * hdr->width * hdr->height; + cursor = g_malloc0(sizeof(*cursor) + size); + cursor->hdr = *hdr; + cursor->default_cursor = FALSE; + cursor->refcount = 1; + data = scursor->data; + + switch (hdr->type) { + case SPICE_CURSOR_TYPE_MONO: + mono_cursor(cursor, data); + break; + case SPICE_CURSOR_TYPE_ALPHA: + memcpy(cursor->data, data, size); + break; + case SPICE_CURSOR_TYPE_COLOR32: + memcpy(cursor->data, data, size); + for (i = 0; i < hdr->width * hdr->height; i++) { + pix_mask = get_pix_mask(data, size, i); + if (pix_mask && *((guint32*)data + i) == 0xffffff) { + cursor->data[i] = get_pix_hack(i, hdr->width); + } else { + cursor->data[i] |= (pix_mask ? 0 : 0xff000000); + } + } + break; + case SPICE_CURSOR_TYPE_COLOR16: + for (i = 0; i < hdr->width * hdr->height; i++) { + pix_mask = get_pix_mask(data, size, i); + pix = *((guint16*)data + i); + if (pix_mask && pix == 0x7fff) { + cursor->data[i] = get_pix_hack(i, hdr->width); + } else { + cursor->data[i] |= ((pix & 0x1f) << 3) | ((pix & 0x3e0) << 6) | + ((pix & 0x7c00) << 9) | (pix_mask ? 0 : 0xff000000); + } + } + break; + case SPICE_CURSOR_TYPE_COLOR4: + size = ((unsigned int)(SPICE_ALIGN(hdr->width, 2) / 2)) * hdr->height; + for (i = 0; i < hdr->width * hdr->height; i++) { + pix_mask = get_pix_mask(data, size + (sizeof(uint32_t) << 4), i); + int idx = (i & 1) ? (data[i >> 1] & 0x0f) : ((data[i >> 1] & 0xf0) >> 4); + pix = *((uint32_t*)(data + size) + idx); + if (pix_mask && pix == 0xffffff) { + cursor->data[i] = get_pix_hack(i, hdr->width); + } else { + cursor->data[i] = pix | (pix_mask ? 0 : 0xff000000); + } + } + + break; + default: + g_warning("%s: unimplemented cursor type %d", __FUNCTION__, + hdr->type); + cursor->default_cursor = TRUE; + goto cache_add; + } + + rgba = (guint8*)cursor->data; + for (i = 0; i < hdr->width * hdr->height; i++) { + val = rgba[0]; + rgba[0] = rgba[2]; + rgba[2] = val; + rgba += 4; + } + +cache_add: + if (scursor->flags & SPICE_CURSOR_FLAGS_CACHE_ME) { + cache_add(c->cursors, hdr->unique, display_cursor_ref(cursor)); + } + + return cursor; +} + +/* coroutine context */ +static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor) +{ + g_return_if_fail(cursor != NULL); + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_SET], 0, + cursor->hdr.width, cursor->hdr.height, + cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y, + cursor->default_cursor ? NULL : cursor->data); +} + +/* coroutine context */ +static void cursor_handle_init(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgCursorInit *init = spice_msg_in_parsed(in); + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + display_cursor *cursor; + + g_return_if_fail(c->init_done == FALSE); + + cache_clear(c->cursors); + cursor = set_cursor(channel, &init->cursor); + c->init_done = TRUE; + if (cursor) + emit_cursor_set(channel, cursor); + if (!init->visible || !cursor) + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0); + if (cursor) + display_cursor_unref(cursor); +} + +/* coroutine context */ +static void cursor_handle_reset(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + CHANNEL_DEBUG(channel, "%s, init_done: %d", __FUNCTION__, c->init_done); + + cache_clear(c->cursors); + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_RESET], 0); + c->init_done = FALSE; +} + +/* coroutine context */ +static void cursor_handle_set(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgCursorSet *set = spice_msg_in_parsed(in); + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + display_cursor *cursor; + + g_return_if_fail(c->init_done == TRUE); + + cursor = set_cursor(channel, &set->cursor); + if (cursor) + emit_cursor_set(channel, cursor); + else + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0); + + + if (cursor) + display_cursor_unref(cursor); +} + +/* coroutine context */ +static void cursor_handle_move(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgCursorMove *move = spice_msg_in_parsed(in); + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + g_return_if_fail(c->init_done == TRUE); + + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_MOVE], 0, + move->position.x, move->position.y); +} + +/* coroutine context */ +static void cursor_handle_hide(SpiceChannel *channel, SpiceMsgIn *in) +{ +#ifdef EXTRA_CHECKS + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + g_return_if_fail(c->init_done == TRUE); +#endif + + g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0); +} + +/* coroutine context */ +static void cursor_handle_trail(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + g_return_if_fail(c->init_done == TRUE); + + g_warning("%s: TODO", __FUNCTION__); +} + +/* coroutine context */ +static void cursor_handle_inval_one(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + SpiceMsgDisplayInvalOne *zap = spice_msg_in_parsed(in); + + g_return_if_fail(c->init_done == TRUE); + + cache_remove(c->cursors, zap->id); +} + +/* coroutine context */ +static void cursor_handle_inval_all(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + cache_clear(c->cursors); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_CURSOR_INIT ] = cursor_handle_init, + [ SPICE_MSG_CURSOR_RESET ] = cursor_handle_reset, + [ SPICE_MSG_CURSOR_SET ] = cursor_handle_set, + [ SPICE_MSG_CURSOR_MOVE ] = cursor_handle_move, + [ SPICE_MSG_CURSOR_HIDE ] = cursor_handle_hide, + [ SPICE_MSG_CURSOR_TRAIL ] = cursor_handle_trail, + [ SPICE_MSG_CURSOR_INVAL_ONE ] = cursor_handle_inval_one, + [ SPICE_MSG_CURSOR_INVAL_ALL ] = cursor_handle_inval_all, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} diff --git a/src/channel-cursor.h b/src/channel-cursor.h new file mode 100644 index 0000000..20f0380 --- /dev/null +++ b/src/channel-cursor.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_CURSOR_CHANNEL_H__ +#define __SPICE_CLIENT_CURSOR_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_CURSOR_CHANNEL (spice_cursor_channel_get_type()) +#define SPICE_CURSOR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_CURSOR_CHANNEL, SpiceCursorChannel)) +#define SPICE_CURSOR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_CURSOR_CHANNEL, SpiceCursorChannelClass)) +#define SPICE_IS_CURSOR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_CURSOR_CHANNEL)) +#define SPICE_IS_CURSOR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_CURSOR_CHANNEL)) +#define SPICE_CURSOR_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_CURSOR_CHANNEL, SpiceCursorChannelClass)) + +typedef struct _SpiceCursorChannel SpiceCursorChannel; +typedef struct _SpiceCursorChannelClass SpiceCursorChannelClass; +typedef struct _SpiceCursorChannelPrivate SpiceCursorChannelPrivate; + +/** + * SpiceCursorChannel: + * + * The #SpiceCursorChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceCursorChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceCursorChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceCursorChannelClass: + * @parent_class: Parent class. + * @cursor_set: Signal class handler for the #SpiceCursorChannel::cursor-set signal. + * @cursor_move: Signal class handler for the #SpiceCursorChannel::cursor-move signal. + * @cursor_hide: Signal class handler for the #SpiceCursorChannel::cursor-hide signal. + * @cursor_reset: Signal class handler for the #SpiceCursorChannel::cursor-reset signal. + * + * Class structure for #SpiceCursorChannel. + */ +struct _SpiceCursorChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*cursor_set)(SpiceCursorChannel *channel, gint width, gint height, + gint hot_x, gint hot_y, gpointer rgba); + void (*cursor_move)(SpiceCursorChannel *channel, gint x, gint y); + void (*cursor_hide)(SpiceCursorChannel *channel); + void (*cursor_reset)(SpiceCursorChannel *channel); + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_cursor_channel_get_type(void); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_CURSOR_CHANNEL_H__ */ diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c new file mode 100644 index 0000000..c752639 --- /dev/null +++ b/src/channel-display-gst.c @@ -0,0 +1,483 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2015-2016 CodeWeavers, Inc + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" + +#include "channel-display-priv.h" + +#include +#include +#include + + +/* GStreamer decoder implementation */ + +typedef struct SpiceGstDecoder { + VideoDecoder base; + + /* ---------- GStreamer pipeline ---------- */ + + GstAppSrc *appsrc; + GstAppSink *appsink; + GstElement *pipeline; + GstClock *clock; + + /* ---------- Decoding and display queues ---------- */ + + uint32_t last_mm_time; + + GMutex queues_mutex; + GQueue *decoding_queue; + GQueue *display_queue; + guint timer_id; +} SpiceGstDecoder; + + +/* ---------- SpiceFrame ---------- */ + +typedef struct _SpiceFrame { + GstClockTime timestamp; + SpiceMsgIn *msg; + GstSample *sample; +} SpiceFrame; + +static SpiceFrame *create_frame(GstBuffer *buffer, SpiceMsgIn *msg) +{ + SpiceFrame *frame = spice_new(SpiceFrame, 1); + frame->timestamp = GST_BUFFER_PTS(buffer); + frame->msg = msg; + spice_msg_in_ref(msg); + frame->sample = NULL; + return frame; +} + +static void free_frame(SpiceFrame *frame) +{ + spice_msg_in_unref(frame->msg); + if (frame->sample) { + gst_sample_unref(frame->sample); + } + free(frame); +} + + +/* ---------- GStreamer pipeline ---------- */ + +static void schedule_frame(SpiceGstDecoder *decoder); + +/* main context */ +static gboolean display_frame(gpointer video_decoder) +{ + SpiceGstDecoder *decoder = (SpiceGstDecoder*)video_decoder; + SpiceFrame *frame; + GstCaps *caps; + gint width, height; + GstStructure *s; + GstBuffer *buffer; + GstMapInfo mapinfo; + + decoder->timer_id = 0; + + g_mutex_lock(&decoder->queues_mutex); + frame = g_queue_pop_head(decoder->display_queue); + g_mutex_unlock(&decoder->queues_mutex); + /* If the queue is empty we don't even need to reschedule */ + g_return_val_if_fail(frame, G_SOURCE_REMOVE); + + if (!frame->sample) { + spice_warning("got a frame without a sample!"); + goto error; + } + + caps = gst_sample_get_caps(frame->sample); + if (!caps) { + spice_warning("GStreamer error: could not get the caps of the sample"); + goto error; + } + + s = gst_caps_get_structure(caps, 0); + if (!gst_structure_get_int(s, "width", &width) || + !gst_structure_get_int(s, "height", &height)) { + spice_warning("GStreamer error: could not get the size of the frame"); + goto error; + } + + buffer = gst_sample_get_buffer(frame->sample); + if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) { + spice_warning("GStreamer error: could not map the buffer"); + goto error; + } + + stream_display_frame(decoder->base.stream, frame->msg, + width, height, mapinfo.data); + gst_buffer_unmap(buffer, &mapinfo); + + error: + free_frame(frame); + schedule_frame(decoder); + return G_SOURCE_REMOVE; +} + +/* main loop or GStreamer streaming thread */ +static void schedule_frame(SpiceGstDecoder *decoder) +{ + guint32 now = stream_get_time(decoder->base.stream); + g_mutex_lock(&decoder->queues_mutex); + + while (!decoder->timer_id) { + SpiceFrame *frame = g_queue_peek_head(decoder->display_queue); + if (!frame) { + break; + } + + SpiceStreamDataHeader *op = spice_msg_in_parsed(frame->msg); + if (now < op->multi_media_time) { + decoder->timer_id = g_timeout_add(op->multi_media_time - now, + display_frame, decoder); + } else if (g_queue_get_length(decoder->display_queue) == 1) { + /* Still attempt to display the least out of date frame so the + * video is not completely frozen for an extended period of time. + */ + decoder->timer_id = g_timeout_add(0, display_frame, decoder); + } else { + SPICE_DEBUG("%s: rendering too late by %u ms (ts: %u, mmtime: %u), dropping", + __FUNCTION__, now - op->multi_media_time, + op->multi_media_time, now); + stream_dropped_frame_on_playback(decoder->base.stream); + g_queue_pop_head(decoder->display_queue); + free_frame(frame); + } + } + + g_mutex_unlock(&decoder->queues_mutex); +} + +/* GStreamer thread + * + * We cannot use GStreamer's signals because they are not always run in + * the main context. So use a callback (lower overhead) and have it pull + * the sample to avoid a race with free_pipeline(). This means queuing the + * decoded frames outside GStreamer. So while we're at it, also schedule + * the frame display ourselves in schedule_frame(). + */ +static GstFlowReturn new_sample(GstAppSink *gstappsink, gpointer video_decoder) +{ + SpiceGstDecoder *decoder = video_decoder; + + GstSample *sample = gst_app_sink_pull_sample(decoder->appsink); + GstBuffer *buffer = sample ? gst_sample_get_buffer(sample) : NULL; + if (sample) { + g_mutex_lock(&decoder->queues_mutex); + + /* gst_app_sink_pull_sample() sometimes returns the same buffer twice + * or buffers that have a modified, and thus unrecognizable, PTS. + * Blindly removing frames from the decoding_queue until we find a + * match would only empty the queue, resulting in later buffers not + * finding a match either, etc. So check the buffer has a matching + * frame first. + */ + SpiceFrame *frame; + GList *l = g_queue_peek_head_link(decoder->decoding_queue); + while (l) { + frame = l->data; + if (frame->timestamp == GST_BUFFER_PTS(buffer)) { + /* The frame is now ready for display */ + frame->sample = sample; + g_queue_push_tail(decoder->display_queue, frame); + + /* Now that we know there is a match, remove it and the older + * frames from the decoding queue. + */ + while ((frame = g_queue_pop_head(decoder->decoding_queue))) { + if (frame->timestamp == GST_BUFFER_PTS(buffer)) { + break; + } + /* The GStreamer pipeline dropped the corresponding + * buffer. + */ + SPICE_DEBUG("the GStreamer pipeline dropped a frame"); + free_frame(frame); + } + break; + } + l = l->next; + } + if (!l) { + spice_warning("got an unexpected decoded buffer!"); + gst_sample_unref(sample); + } + + g_mutex_unlock(&decoder->queues_mutex); + schedule_frame(decoder); + } else { + spice_warning("GStreamer error: could not pull sample"); + } + return GST_FLOW_OK; +} + +static void free_pipeline(SpiceGstDecoder *decoder) +{ + if (!decoder->pipeline) { + return; + } + + gst_element_set_state(decoder->pipeline, GST_STATE_NULL); + gst_object_unref(decoder->appsrc); + gst_object_unref(decoder->appsink); + gst_object_unref(decoder->pipeline); + gst_object_unref(decoder->clock); + decoder->pipeline = NULL; +} + +static gboolean create_pipeline(SpiceGstDecoder *decoder) +{ + const gchar *src_caps, *gstdec_name; + switch (decoder->base.codec_type) { + case SPICE_VIDEO_CODEC_TYPE_MJPEG: + src_caps = "caps=image/jpeg"; + gstdec_name = "jpegdec"; + break; + case SPICE_VIDEO_CODEC_TYPE_VP8: + /* typefind is unable to identify VP8 streams by design. + * See: https://bugzilla.gnome.org/show_bug.cgi?id=756457 + */ + src_caps = "caps=video/x-vp8"; + gstdec_name = "vp8dec"; + break; + case SPICE_VIDEO_CODEC_TYPE_H264: + /* h264 streams detection works fine and setting an incomplete cap + * causes errors. So let typefind do all the work. + */ + src_caps = ""; + gstdec_name = "h264parse ! avdec_h264"; + break; + default: + SPICE_DEBUG("Unknown codec type %d. Trying decodebin.", + decoder->base.codec_type); + src_caps = ""; + gstdec_name = NULL; + break; + } + + /* decodebin will use vaapi if installed, which for a time could + * intentionally crash the application. So only use decodebin as a + * fallback or when SPICE_GSTVIDEO_AUTO is set. + * See: https://bugs.freedesktop.org/show_bug.cgi?id=90884 + */ + if (gstdec_name == NULL || g_getenv("SPICE_GSTVIDEO_AUTO") != NULL) { + gstdec_name = "decodebin"; + } + + /* - We schedule the frame display ourselves so set sync=false on appsink + * so the pipeline decodes them as fast as possible. This will also + * minimize the risk of frames getting lost when we rebuild the + * pipeline. + * - Set max-bytes=0 on appsrc so it does not drop frames that may be + * needed by those that follow. + */ + gchar *desc = g_strdup_printf("appsrc name=src is-live=true format=time max-bytes=0 block=true %s ! %s ! videoconvert ! appsink name=sink caps=video/x-raw,format=BGRx sync=false drop=false", src_caps, gstdec_name); + SPICE_DEBUG("GStreamer pipeline: %s", desc); + + GError *err = NULL; + decoder->pipeline = gst_parse_launch_full(desc, NULL, GST_PARSE_FLAG_FATAL_ERRORS, &err); + g_free(desc); + if (!decoder->pipeline) { + spice_warning("GStreamer error: %s", err->message); + g_clear_error(&err); + return FALSE; + } + + decoder->appsrc = GST_APP_SRC(gst_bin_get_by_name(GST_BIN(decoder->pipeline), "src")); + decoder->appsink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(decoder->pipeline), "sink")); + GstAppSinkCallbacks appsink_cbs = {NULL, NULL, &new_sample, {NULL}}; + gst_app_sink_set_callbacks(decoder->appsink, &appsink_cbs, decoder, NULL); + + decoder->clock = gst_pipeline_get_clock(GST_PIPELINE(decoder->pipeline)); + + if (gst_element_set_state(decoder->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + SPICE_DEBUG("GStreamer error: Unable to set the pipeline to the playing state."); + free_pipeline(decoder); + return FALSE; + } + + return TRUE; +} + + +/* ---------- VideoDecoder's public API ---------- */ + +static void spice_gst_decoder_reschedule(VideoDecoder *video_decoder) +{ + SpiceGstDecoder *decoder = (SpiceGstDecoder*)video_decoder; + if (decoder->timer_id != 0) { + g_source_remove(decoder->timer_id); + decoder->timer_id = 0; + } + schedule_frame(decoder); +} + +/* main context */ +static void spice_gst_decoder_destroy(VideoDecoder *video_decoder) +{ + SpiceGstDecoder *decoder = (SpiceGstDecoder*)video_decoder; + + /* Stop and free the pipeline to ensure there will not be any further + * new_sample() call (clearing thread-safety concerns). + */ + free_pipeline(decoder); + + /* Even if we kept the decoder around, once we return the stream will be + * destroyed making it impossible to display frames. So cancel any + * scheduled display_frame() call and drop the queued frames. + */ + if (decoder->timer_id) { + g_source_remove(decoder->timer_id); + } + g_mutex_clear(&decoder->queues_mutex); + SpiceFrame *frame; + while ((frame = g_queue_pop_head(decoder->decoding_queue))) { + free_frame(frame); + } + g_queue_free(decoder->decoding_queue); + while ((frame = g_queue_pop_head(decoder->display_queue))) { + free_frame(frame); + } + g_queue_free(decoder->display_queue); + + free(decoder); + + /* Don't call gst_deinit() as other parts of the client + * may still be using GStreamer. + */ +} + +static void release_buffer_data(gpointer data) +{ + SpiceMsgIn* frame_msg = (SpiceMsgIn*)data; + spice_msg_in_unref(frame_msg); +} + +static void spice_gst_decoder_queue_frame(VideoDecoder *video_decoder, + SpiceMsgIn *frame_msg, + int32_t latency) +{ + SpiceGstDecoder *decoder = (SpiceGstDecoder*)video_decoder; + + uint8_t *data; + uint32_t size = spice_msg_in_frame_data(frame_msg, &data); + if (size == 0) { + SPICE_DEBUG("got an empty frame buffer!"); + return; + } + + SpiceStreamDataHeader *frame_op = spice_msg_in_parsed(frame_msg); + if (frame_op->multi_media_time < decoder->last_mm_time) { + SPICE_DEBUG("new-frame-time < last-frame-time (%u < %u):" + " resetting stream, id %u", + frame_op->multi_media_time, + decoder->last_mm_time, frame_op->id); + /* Let GStreamer deal with the frame anyway */ + } + decoder->last_mm_time = frame_op->multi_media_time; + + if (latency < 0 && + decoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG) { + /* Dropping MJPEG frames has no impact on those that follow and + * saves CPU so do it. + */ + SPICE_DEBUG("dropping a late MJPEG frame"); + return; + } + + if (!decoder->pipeline && !create_pipeline(decoder)) { + stream_dropped_frame_on_playback(decoder->base.stream); + return; + } + + /* ref() the frame_msg for the buffer */ + spice_msg_in_ref(frame_msg); + GstBuffer *buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, + data, size, 0, size, + frame_msg, &release_buffer_data); + + GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DTS(buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_PTS(buffer) = gst_clock_get_time(decoder->clock) - gst_element_get_base_time(decoder->pipeline) + ((uint64_t)MAX(0, latency)) * 1000 * 1000; + + g_mutex_lock(&decoder->queues_mutex); + g_queue_push_tail(decoder->decoding_queue, create_frame(buffer, frame_msg)); + g_mutex_unlock(&decoder->queues_mutex); + + if (gst_app_src_push_buffer(decoder->appsrc, buffer) != GST_FLOW_OK) { + SPICE_DEBUG("GStreamer error: unable to push frame of size %u", size); + stream_dropped_frame_on_playback(decoder->base.stream); + } +} + +static gboolean gstvideo_init(void) +{ + static int success = 0; + if (!success) { + GError *err = NULL; + if (gst_init_check(NULL, NULL, &err)) { + success = 1; + } else { + spice_warning("Disabling GStreamer video support: %s", err->message); + g_clear_error(&err); + success = -1; + } + } + return success > 0; +} + +G_GNUC_INTERNAL +VideoDecoder* create_gstreamer_decoder(int codec_type, display_stream *stream) +{ + SpiceGstDecoder *decoder = NULL; + + if (gstvideo_init()) { + decoder = spice_new0(SpiceGstDecoder, 1); + decoder->base.destroy = spice_gst_decoder_destroy; + decoder->base.reschedule = spice_gst_decoder_reschedule; + decoder->base.queue_frame = spice_gst_decoder_queue_frame; + decoder->base.codec_type = codec_type; + decoder->base.stream = stream; + g_mutex_init(&decoder->queues_mutex); + decoder->decoding_queue = g_queue_new(); + decoder->display_queue = g_queue_new(); + } + + return (VideoDecoder*)decoder; +} + +G_GNUC_INTERNAL +gboolean gstvideo_has_codec(int codec_type) +{ + gboolean has_codec = FALSE; + + VideoDecoder *decoder = create_gstreamer_decoder(codec_type, NULL); + if (decoder) { + has_codec = create_pipeline((SpiceGstDecoder*)decoder); + decoder->destroy(decoder); + } + + return has_codec; +} diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c new file mode 100644 index 0000000..4976d53 --- /dev/null +++ b/src/channel-display-mjpeg.c @@ -0,0 +1,323 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" + +#include "channel-display-priv.h" + + +/* MJpeg decoder implementation */ + +typedef struct MJpegDecoder { + VideoDecoder base; + + /* ---------- The builtin mjpeg decoder ---------- */ + + struct jpeg_source_mgr mjpeg_src; + struct jpeg_decompress_struct mjpeg_cinfo; + struct jpeg_error_mgr mjpeg_jerr; + + /* ---------- Frame queue ---------- */ + + GQueue *msgq; + SpiceMsgIn *cur_frame_msg; + guint timer_id; + + /* ---------- Output frame data ---------- */ + + uint8_t *out_frame; + uint32_t out_size; +} MJpegDecoder; + + +/* ---------- The JPEG library callbacks ---------- */ + +static void mjpeg_src_init(struct jpeg_decompress_struct *cinfo) +{ + MJpegDecoder *decoder = SPICE_CONTAINEROF(cinfo->src, MJpegDecoder, mjpeg_src); + + uint8_t *data; + cinfo->src->bytes_in_buffer = spice_msg_in_frame_data(decoder->cur_frame_msg, &data); + cinfo->src->next_input_byte = data; +} + +static boolean mjpeg_src_fill(struct jpeg_decompress_struct *cinfo) +{ + g_critical("need more input data"); + return 0; +} + +static void mjpeg_src_skip(struct jpeg_decompress_struct *cinfo, + long num_bytes) +{ + cinfo->src->next_input_byte += num_bytes; +} + +static void mjpeg_src_term(struct jpeg_decompress_struct *cinfo) +{ + /* nothing */ +} + + +/* ---------- Decoder proper ---------- */ + +static void mjpeg_decoder_schedule(MJpegDecoder *decoder); + +/* main context */ +static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder) +{ + MJpegDecoder *decoder = (MJpegDecoder*)video_decoder; + gboolean back_compat = decoder->base.stream->channel->priv->peer_hdr.major_version == 1; + JDIMENSION width, height; + uint8_t *dest; + uint8_t *lines[4]; + + jpeg_read_header(&decoder->mjpeg_cinfo, 1); + width = decoder->mjpeg_cinfo.image_width; + height = decoder->mjpeg_cinfo.image_height; + if (decoder->out_size < width * height * 4) { + g_free(decoder->out_frame); + decoder->out_size = width * height * 4; + decoder->out_frame = g_malloc(decoder->out_size); + } + dest = decoder->out_frame; + +#ifdef JCS_EXTENSIONS + // requires jpeg-turbo + if (back_compat) + decoder->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX; + else + decoder->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX; +#else +#warning "You should consider building with libjpeg-turbo" + decoder->mjpeg_cinfo.out_color_space = JCS_RGB; +#endif + +#ifndef SPICE_QUALITY + decoder->mjpeg_cinfo.dct_method = JDCT_IFAST; + decoder->mjpeg_cinfo.do_fancy_upsampling = FALSE; + decoder->mjpeg_cinfo.do_block_smoothing = FALSE; + decoder->mjpeg_cinfo.dither_mode = JDITHER_ORDERED; +#endif + // TODO: in theory should check cinfo.output_height match with our height + jpeg_start_decompress(&decoder->mjpeg_cinfo); + /* rec_outbuf_height is the recommended size of the output buffer we + * pass to libjpeg for optimum performance + */ + if (decoder->mjpeg_cinfo.rec_outbuf_height > G_N_ELEMENTS(lines)) { + jpeg_abort_decompress(&decoder->mjpeg_cinfo); + g_return_val_if_reached(G_SOURCE_REMOVE); + } + + while (decoder->mjpeg_cinfo.output_scanline < decoder->mjpeg_cinfo.output_height) { + /* only used when JCS_EXTENSIONS is undefined */ + G_GNUC_UNUSED unsigned int lines_read; + + for (unsigned int j = 0; j < decoder->mjpeg_cinfo.rec_outbuf_height; j++) { + lines[j] = dest; +#ifdef JCS_EXTENSIONS + dest += 4 * width; +#else + dest += 3 * width; +#endif + } + lines_read = jpeg_read_scanlines(&decoder->mjpeg_cinfo, lines, + decoder->mjpeg_cinfo.rec_outbuf_height); +#ifndef JCS_EXTENSIONS + { + uint8_t *s = lines[0]; + uint32_t *d = (uint32_t *)s; + + if (back_compat) { + for (unsigned int j = lines_read * width; j > 0; ) { + j -= 1; // reverse order, bad for cache? + d[j] = s[j * 3 + 0] | + s[j * 3 + 1] << 8 | + s[j * 3 + 2] << 16; + } + } else { + for (unsigned int j = lines_read * width; j > 0; ) { + j -= 1; // reverse order, bad for cache? + d[j] = s[j * 3 + 0] << 16 | + s[j * 3 + 1] << 8 | + s[j * 3 + 2]; + } + } + } +#endif + dest = &(decoder->out_frame[decoder->mjpeg_cinfo.output_scanline * width * 4]); + } + jpeg_finish_decompress(&decoder->mjpeg_cinfo); + + /* Display the frame and dispose of it */ + stream_display_frame(decoder->base.stream, decoder->cur_frame_msg, + width, height, decoder->out_frame); + spice_msg_in_unref(decoder->cur_frame_msg); + decoder->cur_frame_msg = NULL; + decoder->timer_id = 0; + + /* Schedule the next frame */ + mjpeg_decoder_schedule(decoder); + + return G_SOURCE_REMOVE; +} + +/* ---------- VideoDecoder's queue scheduling ---------- */ + +static void mjpeg_decoder_schedule(MJpegDecoder *decoder) +{ + SPICE_DEBUG("%s", __FUNCTION__); + if (decoder->timer_id) { + return; + } + + guint32 time = stream_get_time(decoder->base.stream); + SpiceMsgIn *frame_msg = decoder->cur_frame_msg; + decoder->cur_frame_msg = NULL; + do { + if (frame_msg) { + SpiceStreamDataHeader *op = spice_msg_in_parsed(frame_msg); + if (time <= op->multi_media_time) { + guint32 d = op->multi_media_time - time; + decoder->cur_frame_msg = frame_msg; + decoder->timer_id = g_timeout_add(d, mjpeg_decoder_decode_frame, decoder); + break; + } + + SPICE_DEBUG("%s: rendering too late by %u ms (ts: %u, mmtime: %u), dropping ", + __FUNCTION__, time - op->multi_media_time, + op->multi_media_time, time); + stream_dropped_frame_on_playback(decoder->base.stream); + spice_msg_in_unref(frame_msg); + } + frame_msg = g_queue_pop_head(decoder->msgq); + } while (frame_msg); +} + + +/* mjpeg_decoder_drop_queue() helper */ +static void _msg_in_unref_func(gpointer data, gpointer user_data) +{ + spice_msg_in_unref(data); +} + +static void mjpeg_decoder_drop_queue(MJpegDecoder *decoder) +{ + if (decoder->timer_id != 0) { + g_source_remove(decoder->timer_id); + decoder->timer_id = 0; + } + if (decoder->cur_frame_msg) { + spice_msg_in_unref(decoder->cur_frame_msg); + decoder->cur_frame_msg = NULL; + } + g_queue_foreach(decoder->msgq, _msg_in_unref_func, NULL); + g_queue_clear(decoder->msgq); +} + +/* ---------- VideoDecoder's public API ---------- */ + +static void mjpeg_decoder_queue_frame(VideoDecoder *video_decoder, + SpiceMsgIn *frame_msg, int32_t latency) +{ + MJpegDecoder *decoder = (MJpegDecoder*)video_decoder; + SpiceMsgIn *last_msg; + + SPICE_DEBUG("%s", __FUNCTION__); + + last_msg = g_queue_peek_tail(decoder->msgq); + if (last_msg) { + SpiceStreamDataHeader *last_op, *frame_op; + last_op = spice_msg_in_parsed(last_msg); + frame_op = spice_msg_in_parsed(frame_msg); + if (frame_op->multi_media_time < last_op->multi_media_time) { + /* This should really not happen */ + SPICE_DEBUG("new-frame-time < last-frame-time (%u < %u):" + " resetting stream, id %u", + frame_op->multi_media_time, + last_op->multi_media_time, frame_op->id); + mjpeg_decoder_drop_queue(decoder); + } + } + + /* Dropped MJPEG frames don't impact the ones that come after. + * So drop late frames as early as possible to save on processing time. + */ + if (latency < 0) { + return; + } + + spice_msg_in_ref(frame_msg); + g_queue_push_tail(decoder->msgq, frame_msg); + mjpeg_decoder_schedule(decoder); +} + +static void mjpeg_decoder_reschedule(VideoDecoder *video_decoder) +{ + MJpegDecoder *decoder = (MJpegDecoder*)video_decoder; + + SPICE_DEBUG("%s", __FUNCTION__); + if (decoder->timer_id != 0) { + g_source_remove(decoder->timer_id); + decoder->timer_id = 0; + } + mjpeg_decoder_schedule(decoder); +} + +static void mjpeg_decoder_destroy(VideoDecoder* video_decoder) +{ + MJpegDecoder *decoder = (MJpegDecoder*)video_decoder; + + mjpeg_decoder_drop_queue(decoder); + jpeg_destroy_decompress(&decoder->mjpeg_cinfo); + g_free(decoder->out_frame); + free(decoder); +} + +G_GNUC_INTERNAL +VideoDecoder* create_mjpeg_decoder(int codec_type, display_stream *stream) +{ + g_return_val_if_fail(codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG, NULL); + + MJpegDecoder *decoder = spice_new0(MJpegDecoder, 1); + + decoder->base.destroy = mjpeg_decoder_destroy; + decoder->base.reschedule = mjpeg_decoder_reschedule; + decoder->base.queue_frame = mjpeg_decoder_queue_frame; + decoder->base.codec_type = codec_type; + decoder->base.stream = stream; + + decoder->msgq = g_queue_new(); + + decoder->mjpeg_cinfo.err = jpeg_std_error(&decoder->mjpeg_jerr); + jpeg_create_decompress(&decoder->mjpeg_cinfo); + + decoder->mjpeg_src.init_source = mjpeg_src_init; + decoder->mjpeg_src.fill_input_buffer = mjpeg_src_fill; + decoder->mjpeg_src.skip_input_data = mjpeg_src_skip; + decoder->mjpeg_src.resync_to_restart = jpeg_resync_to_restart; + decoder->mjpeg_src.term_source = mjpeg_src_term; + decoder->mjpeg_cinfo.src = &decoder->mjpeg_src; + + /* All the other fields are initialized to zero by spice_new0(). */ + + return (VideoDecoder*)decoder; +} diff --git a/src/channel-display-priv.h b/src/channel-display-priv.h new file mode 100644 index 0000000..3fcf2e2 --- /dev/null +++ b/src/channel-display-priv.h @@ -0,0 +1,146 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef CHANNEL_DISPLAY_PRIV_H_ +# define CHANNEL_DISPLAY_PRIV_H_ + +#include +#ifdef WIN32 +/* We need some hacks to avoid warnings from the jpeg headers */ +#define HAVE_BOOLEAN +#define XMD_H +#endif +#include + +#include "common/canvas_utils.h" +#include "client_sw_canvas.h" +#include "common/ring.h" +#include "common/quic.h" +#include "common/rop3.h" + +G_BEGIN_DECLS + +typedef struct display_stream display_stream; + +typedef struct VideoDecoder VideoDecoder; +struct VideoDecoder { + /* Releases the video decoder's resources */ + void (*destroy)(VideoDecoder *decoder); + + /* Notifies the decoder that the mm-time clock changed. */ + void (*reschedule)(VideoDecoder *video_decoder); + + /* Decompresses the specified frame. + * + * @decoder: The video decoder. + * @frame_msg: The Spice message containing the compressed frame. + * @return: A pointer to the buffer holding the decoded frame. This + * buffer will be invalidated by the next call to + * decode_frame(). + */ + void (*queue_frame)(VideoDecoder *decoder, SpiceMsgIn *frame_msg, int32_t latency); + + /* The format of the encoded video. */ + int codec_type; + + /* The associated display stream. */ + display_stream *stream; +}; + + +/* Instantiates the video decoder for the specified codec. + * + * @codec_type: The format of the video. + * @stream: The associated video stream. + * @return: A pointer to a structure implementing the VideoDecoder methods. + */ +#ifdef HAVE_BUILTIN_MJPEG +VideoDecoder* create_mjpeg_decoder(int codec_type, display_stream *stream); +#endif +#ifdef HAVE_GSTVIDEO +VideoDecoder* create_gstreamer_decoder(int codec_type, display_stream *stream); +gboolean gstvideo_has_codec(int codec_type); +#else +# define gstvideo_has_codec(codec_type) FALSE +#endif + + +typedef struct display_surface { + guint32 surface_id; + bool primary; + enum SpiceSurfaceFmt format; + int width, height, stride, size; + uint8_t *data; + SpiceCanvas *canvas; + SpiceGlzDecoder *glz_decoder; + SpiceZlibDecoder *zlib_decoder; + SpiceJpegDecoder *jpeg_decoder; +} display_surface; + +typedef struct drops_sequence_stats { + uint32_t len; + uint32_t start_mm_time; + uint32_t duration; +} drops_sequence_stats; + +struct display_stream { + SpiceMsgIn *msg_create; + SpiceMsgIn *msg_clip; + + /* from messages */ + display_surface *surface; + const SpiceClip *clip; + QRegion region; + int have_region; + + VideoDecoder *video_decoder; + + SpiceChannel *channel; + + /* stats */ + uint32_t first_frame_mm_time; + uint32_t arrive_late_count; + uint64_t arrive_late_time; + uint32_t num_drops_on_playback; + uint32_t num_input_frames; + drops_sequence_stats cur_drops_seq_stats; + GArray *drops_seqs_stats_arr; + uint32_t num_drops_seqs; + + uint32_t playback_sync_drops_seq_len; + + /* playback quality report to server */ + gboolean report_is_active; + uint32_t report_id; + uint32_t report_max_window; + uint32_t report_timeout; + uint64_t report_start_time; + uint32_t report_start_frame_time; + uint32_t report_num_frames; + uint32_t report_num_drops; + uint32_t report_drops_seq_len; +}; + +guint32 stream_get_time(display_stream *st); +void stream_dropped_frame_on_playback(display_stream *st); +void stream_display_frame(display_stream *st, SpiceMsgIn *frame_msg, uint32_t width, uint32_t height, uint8_t *data); +uint32_t spice_msg_in_frame_data(SpiceMsgIn *frame_msg, uint8_t **data); + + +G_END_DECLS + +#endif // CHANNEL_DISPLAY_PRIV_H_ diff --git a/src/channel-display.c b/src/channel-display.c new file mode 100644 index 0000000..cf9c583 --- /dev/null +++ b/src/channel-display.c @@ -0,0 +1,1855 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-marshal.h" +#include "spice-channel-priv.h" +#include "spice-session-priv.h" +#include "channel-display-priv.h" +#include "decode.h" + +/** + * SECTION:channel-display + * @short_description: remote display area + * @title: Display Channel + * @section_id: + * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client.h + * + * A class that handles the rendering of the remote display and inform + * of its updates. + * + * The creation of the main graphic buffer is signaled with + * #SpiceDisplayChannel::display-primary-create. + * + * The update of regions is notified by + * #SpiceDisplayChannel::display-invalidate signals. + */ + +#define SPICE_DISPLAY_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_DISPLAY_CHANNEL, SpiceDisplayChannelPrivate)) + +#define MONITORS_MAX 256 + +struct _SpiceDisplayChannelPrivate { + GHashTable *surfaces; + display_surface *primary; + display_cache *images; + display_cache *palettes; + SpiceImageCache image_cache; + SpicePaletteCache palette_cache; + SpiceImageSurfaces image_surfaces; + SpiceGlzDecoderWindow *glz_window; + display_stream **streams; + int nstreams; + gboolean mark; + guint mark_false_event_id; + GArray *monitors; + guint monitors_max; + gboolean enable_adaptive_streaming; +#ifdef G_OS_WIN32 + HDC dc; +#endif + SpiceGlScanout scanout; +}; + +G_DEFINE_TYPE(SpiceDisplayChannel, spice_display_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + PROP_MONITORS, + PROP_MONITORS_MAX, + PROP_GL_SCANOUT, +}; + +enum { + SPICE_DISPLAY_PRIMARY_CREATE, + SPICE_DISPLAY_PRIMARY_DESTROY, + SPICE_DISPLAY_INVALIDATE, + SPICE_DISPLAY_MARK, + SPICE_DISPLAY_GL_DRAW, + + SPICE_DISPLAY_LAST_SIGNAL, +}; + +static guint signals[SPICE_DISPLAY_LAST_SIGNAL]; + +static void spice_display_channel_up(SpiceChannel *channel); +static void channel_set_handlers(SpiceChannelClass *klass); + +static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary); +static void clear_streams(SpiceChannel *channel); +static display_surface *find_surface(SpiceDisplayChannelPrivate *c, guint32 surface_id); +static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating); +static void spice_display_channel_reset_capabilities(SpiceChannel *channel); +static void destroy_canvas(display_surface *surface); +static void display_session_mm_time_reset_cb(SpiceSession *session, gpointer data); +static SpiceGlScanout* spice_gl_scanout_copy(const SpiceGlScanout *scanout); + +G_DEFINE_BOXED_TYPE(SpiceGlScanout, spice_gl_scanout, + (GBoxedCopyFunc)spice_gl_scanout_copy, + (GBoxedFreeFunc)spice_gl_scanout_free) + +/* ------------------------------------------------------------------ */ + +static SpiceGlScanout* +spice_gl_scanout_copy(const SpiceGlScanout *scanout) +{ + SpiceGlScanout *so = g_new(SpiceGlScanout, 1); + + *so = *scanout; + so->fd = dup(so->fd); + + return so; +} + +void +spice_gl_scanout_free(SpiceGlScanout *scanout) +{ + close(scanout->fd); + + g_free(scanout); +} + +static void spice_display_channel_dispose(GObject *object) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv; + + if (c->mark_false_event_id != 0) { + g_source_remove(c->mark_false_event_id); + c->mark_false_event_id = 0; + } + + if (c->scanout.fd >= 0) { + close(c->scanout.fd); + c->scanout.fd = -1; + } + + if (G_OBJECT_CLASS(spice_display_channel_parent_class)->dispose) + G_OBJECT_CLASS(spice_display_channel_parent_class)->dispose(object); +} + +static void spice_display_channel_finalize(GObject *object) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv; + + g_clear_pointer(&c->monitors, g_array_unref); + clear_surfaces(SPICE_CHANNEL(object), FALSE); + g_hash_table_unref(c->surfaces); + clear_streams(SPICE_CHANNEL(object)); + g_clear_pointer(&c->palettes, cache_free); + + if (G_OBJECT_CLASS(spice_display_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_display_channel_parent_class)->finalize(object); +} + +static void spice_display_channel_constructed(GObject *object) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv; + SpiceSession *s = spice_channel_get_session(SPICE_CHANNEL(object)); + + g_return_if_fail(s != NULL); + spice_session_get_caches(s, &c->images, &c->glz_window); + c->palettes = cache_new(g_free); + + g_return_if_fail(c->glz_window != NULL); + g_return_if_fail(c->images != NULL); + g_return_if_fail(c->palettes != NULL); + + c->monitors = g_array_new(FALSE, TRUE, sizeof(SpiceDisplayMonitorConfig)); + spice_g_signal_connect_object(s, "mm-time-reset", + G_CALLBACK(display_session_mm_time_reset_cb), + SPICE_CHANNEL(object), 0); + + + if (G_OBJECT_CLASS(spice_display_channel_parent_class)->constructed) + G_OBJECT_CLASS(spice_display_channel_parent_class)->constructed(object); +} + +static void spice_display_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceDisplayChannel *channel = SPICE_DISPLAY_CHANNEL(object); + SpiceDisplayChannelPrivate *c = channel->priv; + + switch (prop_id) { + case PROP_WIDTH: { + g_value_set_uint(value, c->primary ? c->primary->width : 0); + break; + } + case PROP_HEIGHT: { + g_value_set_uint(value, c->primary ? c->primary->height : 0); + break; + } + case PROP_MONITORS: { + g_value_set_boxed(value, c->monitors); + break; + } + case PROP_MONITORS_MAX: { + g_value_set_uint(value, c->monitors_max); + break; + } + case PROP_GL_SCANOUT: { + g_value_set_static_boxed(value, spice_display_get_gl_scanout(channel)); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void spice_display_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/* main or coroutine context */ +static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + /* palettes, images, and glz_window are cleared in the session */ + clear_streams(channel); + clear_surfaces(channel, TRUE); + + SPICE_CHANNEL_CLASS(spice_display_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_display_channel_finalize; + gobject_class->dispose = spice_display_channel_dispose; + gobject_class->get_property = spice_display_get_property; + gobject_class->set_property = spice_display_set_property; + gobject_class->constructed = spice_display_channel_constructed; + + channel_class->channel_up = spice_display_channel_up; + channel_class->channel_reset = spice_display_channel_reset; + channel_class->channel_reset_capabilities = spice_display_channel_reset_capabilities; + + g_object_class_install_property + (gobject_class, PROP_HEIGHT, + g_param_spec_uint("height", + "Display height", + "The primary surface height", + 0, G_MAXUINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_WIDTH, + g_param_spec_uint("width", + "Display width", + "The primary surface width", + 0, G_MAXUINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplayChannel:monitors: + * + * Current monitors configuration. + * + * Since: 0.13 + */ + g_object_class_install_property + (gobject_class, PROP_MONITORS, + g_param_spec_boxed("monitors", + "Display monitors", + "The monitors configuration", + G_TYPE_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplayChannel:monitors-max: + * + * The maximum number of monitors the server or guest supports. + * May change during client lifetime, for instance guest may + * reboot or dynamically adjust this. + * + * Since: 0.13 + */ + g_object_class_install_property + (gobject_class, PROP_MONITORS_MAX, + g_param_spec_uint("monitors-max", + "Max display monitors", + "The current maximum number of monitors", + 1, MONITORS_MAX, 1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplayChannel:gl-scanout: + * @display: the #SpiceDisplayChannel that emitted the signal + * + * The last #SpiceGlScanout received. + * + * Since: 0.31 + */ + g_object_class_install_property + (gobject_class, PROP_GL_SCANOUT, + g_param_spec_boxed("gl-scanout", + "GL scanout", + "GL scanout", + SPICE_TYPE_GL_SCANOUT, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplayChannel::display-primary-create: + * @display: the #SpiceDisplayChannel that emitted the signal + * @format: %SPICE_SURFACE_FMT_32_xRGB or %SPICE_SURFACE_FMT_16_555; + * @width: width resolution + * @height: height resolution + * @stride: the buffer stride ("width" padding) + * @shmid: identifier of the shared memory segment associated with + * the @imgdata, or -1 if not shm + * @imgdata: pointer to surface buffer + * + * The #SpiceDisplayChannel::display-primary-create signal + * provides main display buffer data. + **/ + signals[SPICE_DISPLAY_PRIMARY_CREATE] = + g_signal_new("display-primary-create", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayChannelClass, + display_primary_create), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT_INT_INT_INT_POINTER, + G_TYPE_NONE, + 6, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, + G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER); + + /** + * SpiceDisplayChannel::display-primary-destroy: + * @display: the #SpiceDisplayChannel that emitted the signal + * + * The #SpiceDisplayChannel::display-primary-destroy signal is + * emitted when the primary surface is freed and should not be + * accessed anymore. + **/ + signals[SPICE_DISPLAY_PRIMARY_DESTROY] = + g_signal_new("display-primary-destroy", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayChannelClass, + display_primary_destroy), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * SpiceDisplayChannel::display-invalidate: + * @display: the #SpiceDisplayChannel that emitted the signal + * @x: x position + * @y: y position + * @width: width + * @height: height + * + * The #SpiceDisplayChannel::display-invalidate signal is emitted + * when the rectangular region x/y/w/h of the primary buffer is + * updated. + **/ + signals[SPICE_DISPLAY_INVALIDATE] = + g_signal_new("display-invalidate", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayChannelClass, + display_invalidate), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, + 4, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + + /** + * SpiceDisplayChannel::display-mark: + * @display: the #SpiceDisplayChannel that emitted the signal + * @mark: %TRUE when the display mark has been received + * + * The #SpiceDisplayChannel::display-mark signal is emitted when + * the %RED_DISPLAY_MARK command is received, and the display + * should be exposed. + **/ + signals[SPICE_DISPLAY_MARK] = + g_signal_new("display-mark", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayChannelClass, + display_mark), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + + /** + * SpiceDisplayChannel::gl-draw: + * @display: the #SpiceDisplayChannel that emitted the signal + * @x: x position + * @y: y position + * @width: width + * @height: height + * + * The #SpiceDisplayChannel::draw signal is emitted when the + * rectangular region x/y/w/h of the GL scanout is updated and + * must be drawn. When the draw is finished, you must call + * spice_display_gl_draw_done() in order to release the GL + * resources. + * + * Since: 0.31 + **/ + signals[SPICE_DISPLAY_GL_DRAW] = + g_signal_new("gl-draw", + G_OBJECT_CLASS_TYPE(gobject_class), + 0, 0, NULL, NULL, + g_cclosure_user_marshal_VOID__UINT_UINT_UINT_UINT, + G_TYPE_NONE, + 4, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); + + g_type_class_add_private(klass, sizeof(SpiceDisplayChannelPrivate)); + + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/** + * spice_display_get_primary: + * @channel: a #SpiceDisplayChannel + * @surface_id: a surface id + * @primary: a #SpiceDisplayPrimary + * + * Retrieve primary display surface @surface_id. + * + * Returns: %TRUE if the primary surface was found and its details + * collected in @primary. + */ +gboolean spice_display_get_primary(SpiceChannel *channel, guint32 surface_id, + SpiceDisplayPrimary *primary) +{ + g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), FALSE); + g_return_val_if_fail(primary != NULL, FALSE); + + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + display_surface *surface = find_surface(c, surface_id); + + if (surface == NULL) + return FALSE; + + g_return_val_if_fail(surface->primary, FALSE); + + primary->format = surface->format; + primary->width = surface->width; + primary->height = surface->height; + primary->stride = surface->stride; + primary->shmid = -1; + primary->data = surface->data; + primary->marked = c->mark; + CHANNEL_DEBUG(channel, "get primary %p", primary->data); + + return TRUE; +} + +/** + * spice_display_change_preferred_compression: + * @channel: a #SpiceDisplayChannel + * @compression: a #SpiceImageCompression + * + * Tells the spice server to change the preferred image compression + * for the @channel. + * + * Since: 0.31 + */ +void spice_display_change_preferred_compression(SpiceChannel *channel, gint compression) +{ + SpiceMsgOut *out; + SpiceMsgcDisplayPreferredCompression pref_comp_msg; + + g_return_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel)); + g_return_if_fail(compression > SPICE_IMAGE_COMPRESSION_INVALID && + compression < SPICE_IMAGE_COMPRESSION_ENUM_END); + + if (!spice_channel_test_capability(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION)) { + CHANNEL_DEBUG(channel, "does not have capability to change the preferred compression"); + return; + } + + CHANNEL_DEBUG(channel, "changing preferred compression to %d", compression); + + pref_comp_msg.image_compression = compression; + out = spice_msg_out_new(channel, SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION); + out->marshallers->msgc_display_preferred_compression(out->marshaller, &pref_comp_msg); + spice_msg_out_send_internal(out); +} + +/** + * spice_display_get_gl_scanout: + * @channel: a #SpiceDisplayChannel + * + * Retrieves the GL scanout if available + * + * Returns: the current GL scanout, or %NULL if none or not valid + * + * Since: 0.31 + **/ +const SpiceGlScanout * +spice_display_get_gl_scanout(SpiceDisplayChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL); + + return channel->priv->scanout.fd != -1 ? &channel->priv->scanout : NULL; +} + +/* ------------------------------------------------------------------ */ + +static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t *image) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache); + + cache_add(c->images, id, pixman_image_ref(image)); +} + +typedef struct _WaitImageData +{ + gboolean lossy; + SpiceImageCache *cache; + uint64_t id; + pixman_image_t *image; +} WaitImageData; + +static gboolean wait_image(gpointer data) +{ + gboolean lossy; + WaitImageData *wait = data; + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(wait->cache, SpiceDisplayChannelPrivate, image_cache); + pixman_image_t *image = cache_find_lossy(c->images, wait->id, &lossy); + + if (!image || (lossy && !wait->lossy)) + return FALSE; + + wait->image = pixman_image_ref(image); + + return TRUE; +} + +static pixman_image_t *image_get(SpiceImageCache *cache, uint64_t id) +{ + WaitImageData wait = { + .lossy = TRUE, + .cache = cache, + .id = id, + .image = NULL + }; + if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait)) + SPICE_DEBUG("wait image got cancelled"); + + return wait.image; +} + +static void palette_put(SpicePaletteCache *cache, SpicePalette *palette) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache); + + cache_add(c->palettes, palette->unique, + g_memdup(palette, sizeof(SpicePalette) + + palette->num_ents * sizeof(palette->ents[0]))); +} + +static SpicePalette *palette_get(SpicePaletteCache *cache, uint64_t id) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache); + + /* here the returned pointer is weak, no ref given to caller. it + * seems spice canvas usage is exclusively temporary, so it's ok. + * palette_release is a noop. */ + return cache_find(c->palettes, id); +} + +static void palette_remove(SpicePaletteCache *cache, uint64_t id) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache); + + cache_remove(c->palettes, id); +} + +static void palette_release(SpicePaletteCache *cache, SpicePalette *palette) +{ + /* there is no refcount of palette, see palette_get() */ +} + +static void image_put_lossy(SpiceImageCache *cache, uint64_t id, + pixman_image_t *surface) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache); + +#ifndef NDEBUG + g_warn_if_fail(cache_find(c->images, id) == NULL); +#endif + + cache_add_lossy(c->images, id, pixman_image_ref(surface), TRUE); +} + +static void image_replace_lossy(SpiceImageCache *cache, uint64_t id, + pixman_image_t *surface) +{ + image_put(cache, id, surface); +} + +static pixman_image_t* image_get_lossless(SpiceImageCache *cache, uint64_t id) +{ + WaitImageData wait = { + .lossy = FALSE, + .cache = cache, + .id = id, + .image = NULL + }; + if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait)) + SPICE_DEBUG("wait lossless got cancelled"); + + return wait.image; +} + +static SpiceCanvas *surfaces_get(SpiceImageSurfaces *surfaces, + uint32_t surface_id) +{ + SpiceDisplayChannelPrivate *c = + SPICE_CONTAINEROF(surfaces, SpiceDisplayChannelPrivate, image_surfaces); + + display_surface *s = + find_surface(c, surface_id); + + return s ? s->canvas : NULL; +} + +static SpiceImageCacheOps image_cache_ops = { + .put = image_put, + .get = image_get, + + .put_lossy = image_put_lossy, + .replace_lossy = image_replace_lossy, + .get_lossless = image_get_lossless, +}; + +static SpicePaletteCacheOps palette_cache_ops = { + .put = palette_put, + .get = palette_get, + .release = palette_release, +}; + +static SpiceImageSurfacesOps image_surfaces_ops = { + .get = surfaces_get +}; + +#if defined(G_OS_WIN32) +static HDC create_compatible_dc(void) +{ + HDC dc = CreateCompatibleDC(NULL); + if (!dc) { + g_warning("create compatible DC failed"); + } + return dc; +} +#endif + +static void spice_display_channel_reset_capabilities(SpiceChannel *channel) +{ + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_SIZED_STREAM); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_MONITORS_CONFIG); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_COMPOSITE); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_A8_SURFACE); +#ifdef USE_LZ4 + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_LZ4_COMPRESSION); +#endif + if (SPICE_DISPLAY_CHANNEL(channel)->priv->enable_adaptive_streaming) { + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_STREAM_REPORT); + } +#ifdef G_OS_UNIX + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_GL_SCANOUT); +#endif + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_MULTI_CODEC); +#ifdef HAVE_BUILTIN_MJPEG + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_CODEC_MJPEG); +#endif + if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_MJPEG)) { + spice_channel_set_capability(SPICE_CHANNEL(channel), + SPICE_DISPLAY_CAP_CODEC_MJPEG); + } else { + SPICE_DEBUG("GStreamer does not support the mjpeg codec"); + } + if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_VP8)) { + spice_channel_set_capability(SPICE_CHANNEL(channel), + SPICE_DISPLAY_CAP_CODEC_VP8); + } else { + SPICE_DEBUG("GStreamer does not support the vp8 codec"); + } + if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_H264)) { + spice_channel_set_capability(SPICE_CHANNEL(channel), + SPICE_DISPLAY_CAP_CODEC_H264); + } else { + SPICE_DEBUG("GStreamer does not support the h264 codec"); + } +} + +static void destroy_surface(gpointer data) +{ + display_surface *surface = data; + + destroy_canvas(surface); + g_free(surface); +} + +static void spice_display_channel_init(SpiceDisplayChannel *channel) +{ + SpiceDisplayChannelPrivate *c; + + c = channel->priv = SPICE_DISPLAY_CHANNEL_GET_PRIVATE(channel); + + c->surfaces = g_hash_table_new_full(NULL, NULL, NULL, destroy_surface); + c->image_cache.ops = &image_cache_ops; + c->palette_cache.ops = &palette_cache_ops; + c->image_surfaces.ops = &image_surfaces_ops; +#if defined(G_OS_WIN32) + c->dc = create_compatible_dc(); +#endif + c->monitors_max = 1; + c->scanout.fd = -1; + + if (g_getenv("SPICE_DISABLE_ADAPTIVE_STREAMING")) { + SPICE_DEBUG("adaptive video disabled"); + c->enable_adaptive_streaming = FALSE; + } else { + c->enable_adaptive_streaming = TRUE; + } + spice_display_channel_reset_capabilities(SPICE_CHANNEL(channel)); +} + +/* ------------------------------------------------------------------ */ + +static int create_canvas(SpiceChannel *channel, display_surface *surface) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + if (surface->primary) { + if (c->primary) { + if (c->primary->width == surface->width && + c->primary->height == surface->height) { + CHANNEL_DEBUG(channel, "Reusing existing primary surface"); + return 0; + } + + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0); + + g_hash_table_remove(c->surfaces, GINT_TO_POINTER(c->primary->surface_id)); + } + + CHANNEL_DEBUG(channel, "Create primary canvas"); + } + + surface->data = g_malloc0(surface->size); + + g_return_val_if_fail(c->glz_window, 0); + g_warn_if_fail(surface->canvas == NULL); + g_warn_if_fail(surface->glz_decoder == NULL); + g_warn_if_fail(surface->zlib_decoder == NULL); + g_warn_if_fail(surface->jpeg_decoder == NULL); + + surface->glz_decoder = glz_decoder_new(c->glz_window); + surface->zlib_decoder = zlib_decoder_new(); + surface->jpeg_decoder = jpeg_decoder_new(); + + surface->canvas = canvas_create_for_data(surface->width, + surface->height, + surface->format, + surface->data, + surface->stride, + &c->image_cache, + &c->palette_cache, + &c->image_surfaces, + surface->glz_decoder, + surface->jpeg_decoder, + surface->zlib_decoder); + + g_return_val_if_fail(surface->canvas != NULL, 0); + g_hash_table_insert(c->surfaces, GINT_TO_POINTER(surface->surface_id), surface); + + if (surface->primary) { + g_warn_if_fail(c->primary == NULL); + c->primary = surface; + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_CREATE], 0, + surface->format, surface->width, surface->height, + surface->stride, -1, surface->data); + + if (!spice_channel_test_capability(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG)) { + g_array_set_size(c->monitors, 1); + SpiceDisplayMonitorConfig *config = &g_array_index(c->monitors, SpiceDisplayMonitorConfig, 0); + config->x = config->y = 0; + config->width = surface->width; + config->height = surface->height; + g_coroutine_object_notify(G_OBJECT(channel), "monitors"); + } + } + + return 0; +} + +static void destroy_canvas(display_surface *surface) +{ + if (surface == NULL) + return; + + glz_decoder_destroy(surface->glz_decoder); + zlib_decoder_destroy(surface->zlib_decoder); + jpeg_decoder_destroy(surface->jpeg_decoder); + + g_clear_pointer(&surface->data, g_free); + g_clear_pointer(&surface->canvas, surface->canvas->ops->destroy); +} + +static display_surface *find_surface(SpiceDisplayChannelPrivate *c, guint32 surface_id) +{ + if (c->primary && c->primary->surface_id == surface_id) + return c->primary; + + return g_hash_table_lookup(c->surfaces, GINT_TO_POINTER(surface_id)); +} + +/* main or coroutine context */ +static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + GHashTableIter iter; + display_surface *surface; + + if (!keep_primary) { + c->primary = NULL; + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0); + } + + g_hash_table_iter_init(&iter, c->surfaces); + while (g_hash_table_iter_next(&iter, NULL, (gpointer*)&surface)) { + + if (keep_primary && surface->primary) { + CHANNEL_DEBUG(channel, "keeping existing primary surface, migration or reset"); + continue; + } + + g_hash_table_iter_remove(&iter); + } +} + +/* coroutine context */ +static void emit_invalidate(SpiceChannel *channel, SpiceRect *bbox) +{ + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_INVALIDATE], 0, + bbox->left, bbox->top, + bbox->right - bbox->left, + bbox->bottom - bbox->top); +} + +/* ------------------------------------------------------------------ */ + +/* coroutine context */ +static void spice_display_channel_up(SpiceChannel *channel) +{ + SpiceMsgOut *out; + SpiceSession *s = spice_channel_get_session(channel); + SpiceMsgcDisplayInit init; + int cache_size; + int glz_window_size; + SpiceImageCompression preferred_compression = SPICE_IMAGE_COMPRESSION_INVALID; + + g_object_get(s, + "cache-size", &cache_size, + "glz-window-size", &glz_window_size, + "preferred-compression", &preferred_compression, + NULL); + CHANNEL_DEBUG(channel, "%s: cache_size %d, glz_window_size %d (bytes)", __FUNCTION__, + cache_size, glz_window_size); + init.pixmap_cache_id = 1; + init.glz_dictionary_id = 1; + init.pixmap_cache_size = cache_size / 4; /* pixels */ + init.glz_dictionary_window_size = glz_window_size / 4; /* pixels */ + out = spice_msg_out_new(channel, SPICE_MSGC_DISPLAY_INIT); + out->marshallers->msgc_display_init(out->marshaller, &init); + spice_msg_out_send_internal(out); + + /* notify of existence of this monitor */ + g_coroutine_object_notify(G_OBJECT(channel), "monitors"); + + if (preferred_compression != SPICE_IMAGE_COMPRESSION_INVALID) { + spice_display_change_preferred_compression(channel, preferred_compression); + } +} + +#define DRAW(type) { \ + display_surface *surface = \ + find_surface(SPICE_DISPLAY_CHANNEL(channel)->priv, \ + op->base.surface_id); \ + g_return_if_fail(surface != NULL); \ + surface->canvas->ops->draw_##type(surface->canvas, &op->base.box, \ + &op->base.clip, &op->data); \ + if (surface->primary) { \ + emit_invalidate(channel, &op->base.box); \ + } \ +} + +/* coroutine context */ +static void display_handle_mode(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgDisplayMode *mode = spice_msg_in_parsed(in); + display_surface *surface; + + g_warn_if_fail(c->mark == FALSE); + + surface = g_new0(display_surface, 1); + surface->format = mode->bits == 32 ? + SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555; + surface->width = mode->x_res; + surface->height = mode->y_res; + surface->stride = surface->width * 4; + surface->size = surface->height * surface->stride; + surface->primary = true; + create_canvas(channel, surface); +} + +/* coroutine context */ +static void display_handle_mark(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + CHANNEL_DEBUG(channel, "%s", __FUNCTION__); + g_return_if_fail(c->primary != NULL); +#ifdef EXTRA_CHECKS + g_warn_if_fail(c->mark == FALSE); +#endif + + c->mark = TRUE; + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, TRUE); +} + +/* coroutine context */ +static void display_handle_reset(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + display_surface *surface = c->primary; + + CHANNEL_DEBUG(channel, "%s: TODO detach_from_screen", __FUNCTION__); + + if (surface != NULL) + surface->canvas->ops->clear(surface->canvas); + + cache_clear(c->palettes); + + c->mark = FALSE; + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, FALSE); +} + +/* coroutine context */ +static void display_handle_copy_bits(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayCopyBits *op = spice_msg_in_parsed(in); + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + display_surface *surface = find_surface(c, op->base.surface_id); + + g_return_if_fail(surface != NULL); + surface->canvas->ops->copy_bits(surface->canvas, &op->base.box, + &op->base.clip, &op->src_pos); + if (surface->primary) { + emit_invalidate(channel, &op->base.box); + } +} + +/* coroutine context */ +static void display_handle_inv_list(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceResourceList *list = spice_msg_in_parsed(in); + int i; + + for (i = 0; i < list->count; i++) { + guint64 id = list->resources[i].id; + + switch (list->resources[i].type) { + case SPICE_RES_TYPE_PIXMAP: + if (!cache_remove(c->images, id)) + SPICE_DEBUG("fail to remove image %" G_GUINT64_FORMAT, id); + break; + default: + g_return_if_reached(); + break; + } + } +} + +/* coroutine context */ +static void display_handle_inv_pixmap_all(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + spice_channel_handle_wait_for_channels(channel, in); + cache_clear(c->images); +} + +/* coroutine context */ +static void display_handle_inv_palette(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgDisplayInvalOne* op = spice_msg_in_parsed(in); + + palette_remove(&c->palette_cache, op->id); +} + +/* coroutine context */ +static void display_handle_inv_palette_all(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + cache_clear(c->palettes); +} + +/* ------------------------------------------------------------------ */ + +static void display_update_stream_region(display_stream *st) +{ + int i; + + switch (st->clip->type) { + case SPICE_CLIP_TYPE_RECTS: + region_clear(&st->region); + for (i = 0; i < st->clip->rects->num_rects; i++) { + region_add(&st->region, &st->clip->rects->rects[i]); + } + st->have_region = true; + break; + case SPICE_CLIP_TYPE_NONE: + default: + st->have_region = false; + break; + } +} + +/* coroutine context */ +static void display_handle_stream_create(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgDisplayStreamCreate *op = spice_msg_in_parsed(in); + display_stream *st; + + CHANNEL_DEBUG(channel, "%s: id %u", __FUNCTION__, op->id); + + if (op->id >= c->nstreams) { + int n = c->nstreams; + if (!c->nstreams) { + c->nstreams = 1; + } + while (op->id >= c->nstreams) { + c->nstreams *= 2; + } + c->streams = realloc(c->streams, c->nstreams * sizeof(c->streams[0])); + memset(c->streams + n, 0, (c->nstreams - n) * sizeof(c->streams[0])); + } + g_return_if_fail(c->streams[op->id] == NULL); + c->streams[op->id] = g_new0(display_stream, 1); + st = c->streams[op->id]; + + st->msg_create = in; + spice_msg_in_ref(in); + st->clip = &op->clip; + st->surface = find_surface(c, op->surface_id); + st->channel = channel; + st->drops_seqs_stats_arr = g_array_new(FALSE, FALSE, sizeof(drops_sequence_stats)); + + region_init(&st->region); + display_update_stream_region(st); + + switch (op->codec_type) { +#ifdef HAVE_BUILTIN_MJPEG + case SPICE_VIDEO_CODEC_TYPE_MJPEG: + st->video_decoder = create_mjpeg_decoder(op->codec_type, st); + break; +#endif + default: +#ifdef HAVE_GSTVIDEO + st->video_decoder = create_gstreamer_decoder(op->codec_type, st); +#else + st->video_decoder = NULL; +#endif + } + if (st->video_decoder == NULL) { + spice_printerr("could not create a video decoder for codec %u", op->codec_type); + } +} + +static const SpiceRect *stream_get_dest(display_stream *st, SpiceMsgIn *frame_msg) +{ + if (frame_msg == NULL || + spice_msg_in_type(frame_msg) != SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) { + SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create); + + return &info->dest; + } else { + SpiceMsgDisplayStreamDataSized *op = spice_msg_in_parsed(frame_msg); + + return &op->dest; + } + +} + +static uint32_t stream_get_flags(display_stream *st) +{ + SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create); + + return info->flags; +} + +G_GNUC_INTERNAL +uint32_t spice_msg_in_frame_data(SpiceMsgIn *frame_msg, uint8_t **data) +{ + switch (spice_msg_in_type(frame_msg)) { + case SPICE_MSG_DISPLAY_STREAM_DATA: { + SpiceMsgDisplayStreamData *op = spice_msg_in_parsed(frame_msg); + *data = op->data; + return op->data_size; + } + case SPICE_MSG_DISPLAY_STREAM_DATA_SIZED: { + SpiceMsgDisplayStreamDataSized *op = spice_msg_in_parsed(frame_msg); + *data = op->data; + return op->data_size; + } + default: + *data = NULL; + g_return_val_if_reached(0); + } +} + +G_GNUC_INTERNAL +guint32 stream_get_time(display_stream *st) +{ + SpiceSession *session = spice_channel_get_session(st->channel); + return session ? spice_session_get_mm_time(session) : 0; +} + +/* coroutine or main context */ +G_GNUC_INTERNAL +void stream_dropped_frame_on_playback(display_stream *st) +{ + st->num_drops_on_playback++; +} + +/* main context */ +G_GNUC_INTERNAL +void stream_display_frame(display_stream *st, SpiceMsgIn *frame_msg, + uint32_t width, uint32_t height, uint8_t *data) +{ + const SpiceRect *dest; + int stride; + + dest = stream_get_dest(st, frame_msg); + + stride = width * sizeof(uint32_t); + if (!(stream_get_flags(st) & SPICE_STREAM_FLAGS_TOP_DOWN)) { + data += stride * (height - 1); + stride = -stride; + } + + st->surface->canvas->ops->put_image(st->surface->canvas, +#ifdef G_OS_WIN32 + SPICE_DISPLAY_CHANNEL(st->channel)->priv->dc, +#endif + dest, data, + width, height, stride, + st->have_region ? &st->region : NULL); + + if (st->surface->primary) + g_signal_emit(st->channel, signals[SPICE_DISPLAY_INVALIDATE], 0, + dest->left, dest->top, + dest->right - dest->left, + dest->bottom - dest->top); +} + +/* after a sequence of 3 drops, push a report to the server, even + * if the report window is bigger */ +#define STREAM_REPORT_DROP_SEQ_LEN_LIMIT 3 + +static void display_update_stream_report(SpiceDisplayChannel *channel, uint32_t stream_id, + uint32_t frame_time, int32_t latency) +{ + display_stream *st = channel->priv->streams[stream_id]; + guint64 now; + + if (!st->report_is_active) { + return; + } + now = g_get_monotonic_time(); + + if (st->report_num_frames == 0) { + st->report_start_frame_time = frame_time; + st->report_start_time = now; + } + st->report_num_frames++; + + if (latency < 0) { // drop + st->report_num_drops++; + st->report_drops_seq_len++; + } else { + st->report_drops_seq_len = 0; + } + + if (st->report_num_frames >= st->report_max_window || + now - st->report_start_time >= st->report_timeout || + st->report_drops_seq_len >= STREAM_REPORT_DROP_SEQ_LEN_LIMIT) { + SpiceMsgcDisplayStreamReport report; + SpiceSession *session = spice_channel_get_session(SPICE_CHANNEL(channel)); + SpiceMsgOut *msg; + + report.stream_id = stream_id; + report.unique_id = st->report_id; + report.start_frame_mm_time = st->report_start_frame_time; + report.end_frame_mm_time = frame_time; + report.num_frames = st->report_num_frames; + report.num_drops = st-> report_num_drops; + report.last_frame_delay = latency; + if (spice_session_is_playback_active(session)) { + report.audio_delay = spice_session_get_playback_latency(session); + } else { + report.audio_delay = UINT_MAX; + } + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_DISPLAY_STREAM_REPORT); + msg->marshallers->msgc_display_stream_report(msg->marshaller, &report); + spice_msg_out_send(msg); + + st->report_start_time = 0; + st->report_start_frame_time = 0; + st->report_num_frames = 0; + st->report_num_drops = 0; + st->report_drops_seq_len = 0; + } +} + +/* + * Migration can occur between 2 spice-servers with different mm-times. + * Then, the following cases can happen after migration completes: + * (We refer to src/dst-time as the mm-times on the src/dst servers): + * + * (case 1) Frames with time ~= dst-time arrive to the client before the + * playback-channel updates the session's mm-time (i.e., the mm_time + * of the session is still based on the src-time). + * (a) If src-time < dst-time: + * display_stream_schedule schedules the next rendering to + * ~(dst-time - src-time) milliseconds from now. + * Since we assume monotonic mm_time, display_stream_schedule, + * returns immediately when a rendering timeout + * has already been set, and doesn't update the timeout, + * even after the mm_time is updated. + * When src-time << dst-time, a significant video frames loss will occur. + * (b) If src-time > dst-time + * Frames will be dropped till the mm-time will be updated. + * (case 2) mm-time is synced with dst-time, but frames that were in the command + * ring during migration still arrive (such frames hold src-time). + * (a) If src-time < dst-time + * The frames that hold src-time will be dropped, since their + * mm_time < session-mm_time. But all the new frames that are generated in + * the driver after migration, will be rendered appropriately. + * (b) If src-time > dst-time + * Similar consequences as in 1 (a) + * case 2 is less likely, since at takes at least 20 frames till the dst-server re-identifies + * the video stream and starts sending stream data + * + * display_session_mm_time_reset_cb handles case 1.a by notifying the + * video decoders through their reschedule() method, and case 2.b is handled + * directly by the video decoders in their queue_frame() method + */ + +/* main context */ +static void display_session_mm_time_reset_cb(SpiceSession *session, gpointer data) +{ + SpiceChannel *channel = data; + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + guint i; + + CHANNEL_DEBUG(channel, "%s", __FUNCTION__); + + for (i = 0; i < c->nstreams; i++) { + display_stream *st; + + if (c->streams[i] == NULL) { + continue; + } + SPICE_DEBUG("%s: stream-id %u", __FUNCTION__, i); + st = c->streams[i]; + st->video_decoder->reschedule(st->video_decoder); + } +} + +#define STREAM_PLAYBACK_SYNC_DROP_SEQ_LEN_LIMIT 5 + +/* coroutine context */ +static void display_handle_stream_data(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceStreamDataHeader *op = spice_msg_in_parsed(in); + display_stream *st; + guint32 mmtime; + int32_t latency; + + g_return_if_fail(c != NULL); + g_return_if_fail(c->streams != NULL); + g_return_if_fail(c->nstreams > op->id); + + st = c->streams[op->id]; + mmtime = stream_get_time(st); + + if (spice_msg_in_type(in) == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) { + CHANNEL_DEBUG(channel, "stream %u contains sized data", op->id); + } + + if (op->multi_media_time == 0) { + g_critical("Received frame with invalid 0 timestamp! perhaps wrong graphic driver?"); + op->multi_media_time = mmtime + 100; /* workaround... */ + } + + if (!st->num_input_frames) { + st->first_frame_mm_time = op->multi_media_time; + } + st->num_input_frames++; + + latency = op->multi_media_time - mmtime; + if (latency < 0) { + CHANNEL_DEBUG(channel, "stream data too late by %u ms (ts: %u, mmtime: %u), dropping", + mmtime - op->multi_media_time, op->multi_media_time, mmtime); + st->arrive_late_time += mmtime - op->multi_media_time; + st->arrive_late_count++; + + if (!st->cur_drops_seq_stats.len) { + st->cur_drops_seq_stats.start_mm_time = op->multi_media_time; + } + st->cur_drops_seq_stats.len++; + st->playback_sync_drops_seq_len++; + } else { + CHANNEL_DEBUG(channel, "video latency: %d", latency); + if (st->cur_drops_seq_stats.len) { + st->cur_drops_seq_stats.duration = op->multi_media_time - + st->cur_drops_seq_stats.start_mm_time; + g_array_append_val(st->drops_seqs_stats_arr, st->cur_drops_seq_stats); + memset(&st->cur_drops_seq_stats, 0, sizeof(st->cur_drops_seq_stats)); + st->num_drops_seqs++; + } + st->playback_sync_drops_seq_len = 0; + } + + /* Let the video decoder queue the frames so it can optimize their + * decoding and best decide if/when to drop them when they are late, + * taking into account the impact on later frames. + */ + st->video_decoder->queue_frame(st->video_decoder, in, latency); + if (c->enable_adaptive_streaming) { + display_update_stream_report(SPICE_DISPLAY_CHANNEL(channel), op->id, + op->multi_media_time, latency); + if (st->playback_sync_drops_seq_len >= STREAM_PLAYBACK_SYNC_DROP_SEQ_LEN_LIMIT) { + spice_session_sync_playback_latency(spice_channel_get_session(channel)); + st->playback_sync_drops_seq_len = 0; + } + } +} + +/* coroutine context */ +static void display_handle_stream_clip(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgDisplayStreamClip *op = spice_msg_in_parsed(in); + display_stream *st; + + g_return_if_fail(c != NULL); + g_return_if_fail(c->streams != NULL); + g_return_if_fail(c->nstreams > op->id); + + st = c->streams[op->id]; + + if (st->msg_clip) { + spice_msg_in_unref(st->msg_clip); + } + spice_msg_in_ref(in); + st->msg_clip = in; + st->clip = &op->clip; + display_update_stream_region(st); +} + +static void destroy_stream(SpiceChannel *channel, int id) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + display_stream *st; + guint64 drops_duration_total = 0; + guint32 num_out_frames; + int i; + + g_return_if_fail(c != NULL); + g_return_if_fail(c->streams != NULL); + g_return_if_fail(c->nstreams > id); + + st = c->streams[id]; + if (!st) + return; + + num_out_frames = st->num_input_frames - st->arrive_late_count - st->num_drops_on_playback; + CHANNEL_DEBUG(channel, "%s: id=%d #in-frames=%u out/in=%.2f " + "#drops-on-receive=%u avg-late-time(ms)=%.2f " + "#drops-on-playback=%u", __FUNCTION__, + id, + st->num_input_frames, + num_out_frames / (double)st->num_input_frames, + st->arrive_late_count, + st->arrive_late_count ? st->arrive_late_time / ((double)st->arrive_late_count): 0, + st->num_drops_on_playback); + if (st->num_drops_seqs) { + CHANNEL_DEBUG(channel, "%s: #drops-sequences=%u ==>", __FUNCTION__, st->num_drops_seqs); + } + for (i = 0; i < st->num_drops_seqs; i++) { + drops_sequence_stats *stats = &g_array_index(st->drops_seqs_stats_arr, + drops_sequence_stats, + i); + drops_duration_total += stats->duration; + CHANNEL_DEBUG(channel, "%s: \t len=%u start-ms=%u duration-ms=%u", __FUNCTION__, + stats->len, + stats->start_mm_time - st->first_frame_mm_time, + stats->duration); + } + if (st->num_drops_seqs) { + CHANNEL_DEBUG(channel, "%s: drops-total-duration=%"G_GUINT64_FORMAT" ==>", __FUNCTION__, drops_duration_total); + } + + g_array_free(st->drops_seqs_stats_arr, TRUE); + + if (st->video_decoder) { + st->video_decoder->destroy(st->video_decoder); + } + + if (st->msg_clip) + spice_msg_in_unref(st->msg_clip); + spice_msg_in_unref(st->msg_create); + + g_free(st); + c->streams[id] = NULL; +} + +static void clear_streams(SpiceChannel *channel) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + int i; + + for (i = 0; i < c->nstreams; i++) { + destroy_stream(channel, i); + } + g_clear_pointer(&c->streams, g_free); + c->nstreams = 0; +} + +/* coroutine context */ +static void display_handle_stream_destroy(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayStreamDestroy *op = spice_msg_in_parsed(in); + + g_return_if_fail(op != NULL); + CHANNEL_DEBUG(channel, "%s: id %u", __FUNCTION__, op->id); + destroy_stream(channel, op->id); +} + +/* coroutine context */ +static void display_handle_stream_destroy_all(SpiceChannel *channel, SpiceMsgIn *in) +{ + clear_streams(channel); +} + +/* coroutine context */ +static void display_handle_stream_activate_report(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgDisplayStreamActivateReport *op = spice_msg_in_parsed(in); + display_stream *st; + + g_return_if_fail(c != NULL); + g_return_if_fail(c->streams != NULL); + g_return_if_fail(c->nstreams > op->stream_id); + + st = c->streams[op->stream_id]; + g_return_if_fail(st != NULL); + + st->report_is_active = TRUE; + st->report_id = op->unique_id; + st->report_max_window = op->max_window_size; + st->report_timeout = op->timeout_ms * 1000; + st->report_start_time = 0; + st->report_start_frame_time = 0; + st->report_num_frames = 0; + st->report_num_drops = 0; + st->report_drops_seq_len = 0; +} + +/* ------------------------------------------------------------------ */ + +/* coroutine context */ +static void display_handle_draw_fill(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawFill *op = spice_msg_in_parsed(in); + DRAW(fill); +} + +/* coroutine context */ +static void display_handle_draw_opaque(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawOpaque *op = spice_msg_in_parsed(in); + DRAW(opaque); +} + +/* coroutine context */ +static void display_handle_draw_copy(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawCopy *op = spice_msg_in_parsed(in); + DRAW(copy); +} + +/* coroutine context */ +static void display_handle_draw_blend(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawBlend *op = spice_msg_in_parsed(in); + DRAW(blend); +} + +/* coroutine context */ +static void display_handle_draw_blackness(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawBlackness *op = spice_msg_in_parsed(in); + DRAW(blackness); +} + +static void display_handle_draw_whiteness(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawWhiteness *op = spice_msg_in_parsed(in); + DRAW(whiteness); +} + +/* coroutine context */ +static void display_handle_draw_invers(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawInvers *op = spice_msg_in_parsed(in); + DRAW(invers); +} + +/* coroutine context */ +static void display_handle_draw_rop3(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawRop3 *op = spice_msg_in_parsed(in); + DRAW(rop3); +} + +/* coroutine context */ +static void display_handle_draw_stroke(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawStroke *op = spice_msg_in_parsed(in); + DRAW(stroke); +} + +/* coroutine context */ +static void display_handle_draw_text(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawText *op = spice_msg_in_parsed(in); + DRAW(text); +} + +/* coroutine context */ +static void display_handle_draw_transparent(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawTransparent *op = spice_msg_in_parsed(in); + DRAW(transparent); +} + +/* coroutine context */ +static void display_handle_draw_alpha_blend(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawAlphaBlend *op = spice_msg_in_parsed(in); + DRAW(alpha_blend); +} + +/* coroutine context */ +static void display_handle_draw_composite(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayDrawComposite *op = spice_msg_in_parsed(in); + DRAW(composite); +} + +/* coroutine context */ +static void display_handle_surface_create(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in); + display_surface *surface = g_new0(display_surface, 1); + + surface->surface_id = create->surface_id; + surface->format = create->format; + surface->width = create->width; + surface->height = create->height; + surface->stride = create->width * 4; + surface->size = surface->height * surface->stride; + + if (create->flags & SPICE_SURFACE_FLAGS_PRIMARY) { + SPICE_DEBUG("primary flags: %x", create->flags); + surface->primary = true; + create_canvas(channel, surface); + if (c->mark_false_event_id != 0) { + g_source_remove(c->mark_false_event_id); + c->mark_false_event_id = FALSE; + } + } else { + surface->primary = false; + create_canvas(channel, surface); + } +} + +static gboolean display_mark_false(gpointer data) +{ + SpiceChannel *channel = data; + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + c->mark = FALSE; + g_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, FALSE); + + c->mark_false_event_id = 0; + return FALSE; +} + +/* coroutine context */ +static void display_handle_surface_destroy(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgSurfaceDestroy *destroy = spice_msg_in_parsed(in); + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + display_surface *surface; + + g_return_if_fail(destroy != NULL); + + surface = find_surface(c, destroy->surface_id); + if (surface == NULL) { + /* this is not a problem in spicec, it happens as well and returns.. */ + /* g_warn_if_reached(); */ + return; + } + if (surface->primary) { + int id = spice_channel_get_channel_id(channel); + CHANNEL_DEBUG(channel, "%d: FIXME primary destroy, but is display really disabled?", id); + /* this is done with a timeout in spicec as well, it's *ugly* */ + if (id != 0 && c->mark_false_event_id == 0) { + c->mark_false_event_id = g_timeout_add_seconds(1, display_mark_false, channel); + } + c->primary = NULL; + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0); + } + + g_hash_table_remove(c->surfaces, GINT_TO_POINTER(surface->surface_id)); +} + +#define CLAMP_CHECK(x, low, high) (((x) > (high)) ? TRUE : (((x) < (low)) ? TRUE : FALSE)) + +/* coroutine context */ +static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayMonitorsConfig *config = spice_msg_in_parsed(in); + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + guint i; + + g_return_if_fail(config != NULL); + + if (config->count == 0) { + CHANNEL_DEBUG(channel, "received empty monitor config"); + return; + } + + CHANNEL_DEBUG(channel, "received new monitors config from guest: n: %d/%d", config->count, config->max_allowed); + + c->monitors_max = config->max_allowed; + if (CLAMP_CHECK(c->monitors_max, 1, MONITORS_MAX)) { + g_warning("MonitorConfig max_allowed is not within permitted range, clamping"); + c->monitors_max = CLAMP(c->monitors_max, 1, MONITORS_MAX); + } + + if (CLAMP_CHECK(config->count, 1, c->monitors_max)) { + g_warning("MonitorConfig count is not within permitted range, clamping"); + config->count = CLAMP(config->count, 1, c->monitors_max); + } + + c->monitors = g_array_set_size(c->monitors, config->count); + + for (i = 0; i < config->count; i++) { + SpiceDisplayMonitorConfig *mc = &g_array_index(c->monitors, SpiceDisplayMonitorConfig, i); + SpiceHead *head = &config->heads[i]; + CHANNEL_DEBUG(channel, "monitor id: %u, surface id: %u, +%u+%u-%ux%u", + head->id, head->surface_id, + head->x, head->y, head->width, head->height); + mc->id = head->id; + mc->surface_id = head->surface_id; + mc->x = head->x; + mc->y = head->y; + mc->width = head->width; + mc->height = head->height; + } + + g_coroutine_object_notify(G_OBJECT(channel), "monitors"); +} + + +#ifdef G_OS_UNIX +/* coroutine context */ +static void display_handle_gl_scanout_unix(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannel *display = SPICE_DISPLAY_CHANNEL(channel); + SpiceDisplayChannelPrivate *c = display->priv; + SpiceMsgDisplayGlScanoutUnix *scanout = spice_msg_in_parsed(in); + + scanout->drm_dma_buf_fd = -1; + if (scanout->drm_fourcc_format != 0) { + scanout->drm_dma_buf_fd = spice_channel_unix_read_fd(channel); + CHANNEL_DEBUG(channel, "gl scanout fd: %d", scanout->drm_dma_buf_fd); + } + + c->scanout.y0top = scanout->flags & SPICE_GL_SCANOUT_FLAGS_Y0TOP; + if (c->scanout.fd >= 0) + close(c->scanout.fd); + c->scanout.fd = scanout->drm_dma_buf_fd; + c->scanout.width = scanout->width; + c->scanout.height = scanout->height; + c->scanout.stride = scanout->stride; + c->scanout.format = scanout->drm_fourcc_format; + + g_coroutine_object_notify(G_OBJECT(channel), "gl-scanout"); +} +#endif + +/* coroutine context */ +static void display_handle_gl_draw(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgDisplayGlDraw *draw = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "gl draw %ux%u+%u+%u", + draw->w, draw->h, draw->x, draw->y); + + g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_GL_DRAW], 0, + draw->x, draw->y, + draw->w, draw->h); +} + +/** + * spice_display_gl_draw_done: + * @channel: a #SpiceDisplayChannel + * + * After a SpiceDisplayChannel::gl-draw is emitted, the client should + * draw the current display with the current GL scanout, and must + * release the GL resource with a call to spice_display_gl_draw_done() + * (failing to do so for each gl-draw may result in a frozen display). + * + * Since: 0.31 + **/ +void spice_display_gl_draw_done(SpiceDisplayChannel *display) +{ + SpiceChannel *channel; + SpiceMsgOut *out; + + g_return_if_fail(SPICE_IS_DISPLAY_CHANNEL(display)); + channel = SPICE_CHANNEL(display); + + out = spice_msg_out_new(channel, SPICE_MSGC_DISPLAY_GL_DRAW_DONE); + out->marshallers->msgc_display_gl_draw_done(out->marshaller, NULL); + spice_msg_out_send_internal(out); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_DISPLAY_MODE ] = display_handle_mode, + [ SPICE_MSG_DISPLAY_MARK ] = display_handle_mark, + [ SPICE_MSG_DISPLAY_RESET ] = display_handle_reset, + [ SPICE_MSG_DISPLAY_COPY_BITS ] = display_handle_copy_bits, + [ SPICE_MSG_DISPLAY_INVAL_LIST ] = display_handle_inv_list, + [ SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS ] = display_handle_inv_pixmap_all, + [ SPICE_MSG_DISPLAY_INVAL_PALETTE ] = display_handle_inv_palette, + [ SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES ] = display_handle_inv_palette_all, + + [ SPICE_MSG_DISPLAY_STREAM_CREATE ] = display_handle_stream_create, + [ SPICE_MSG_DISPLAY_STREAM_DATA ] = display_handle_stream_data, + [ SPICE_MSG_DISPLAY_STREAM_CLIP ] = display_handle_stream_clip, + [ SPICE_MSG_DISPLAY_STREAM_DESTROY ] = display_handle_stream_destroy, + [ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] = display_handle_stream_destroy_all, + [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ] = display_handle_stream_data, + [ SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT ] = display_handle_stream_activate_report, + + [ SPICE_MSG_DISPLAY_DRAW_FILL ] = display_handle_draw_fill, + [ SPICE_MSG_DISPLAY_DRAW_OPAQUE ] = display_handle_draw_opaque, + [ SPICE_MSG_DISPLAY_DRAW_COPY ] = display_handle_draw_copy, + [ SPICE_MSG_DISPLAY_DRAW_BLEND ] = display_handle_draw_blend, + [ SPICE_MSG_DISPLAY_DRAW_BLACKNESS ] = display_handle_draw_blackness, + [ SPICE_MSG_DISPLAY_DRAW_WHITENESS ] = display_handle_draw_whiteness, + [ SPICE_MSG_DISPLAY_DRAW_INVERS ] = display_handle_draw_invers, + [ SPICE_MSG_DISPLAY_DRAW_ROP3 ] = display_handle_draw_rop3, + [ SPICE_MSG_DISPLAY_DRAW_STROKE ] = display_handle_draw_stroke, + [ SPICE_MSG_DISPLAY_DRAW_TEXT ] = display_handle_draw_text, + [ SPICE_MSG_DISPLAY_DRAW_TRANSPARENT ] = display_handle_draw_transparent, + [ SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND ] = display_handle_draw_alpha_blend, + [ SPICE_MSG_DISPLAY_DRAW_COMPOSITE ] = display_handle_draw_composite, + + [ SPICE_MSG_DISPLAY_SURFACE_CREATE ] = display_handle_surface_create, + [ SPICE_MSG_DISPLAY_SURFACE_DESTROY ] = display_handle_surface_destroy, + + [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ] = display_handle_monitors_config, +#ifdef G_OS_UNIX + [ SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX ] = display_handle_gl_scanout_unix, +#endif + [ SPICE_MSG_DISPLAY_GL_DRAW ] = display_handle_gl_draw, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} diff --git a/src/channel-display.h b/src/channel-display.h new file mode 100644 index 0000000..ad82a16 --- /dev/null +++ b/src/channel-display.h @@ -0,0 +1,161 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_DISPLAY_CHANNEL_H__ +#define __SPICE_CLIENT_DISPLAY_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_DISPLAY_CHANNEL (spice_display_channel_get_type()) +#define SPICE_DISPLAY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_DISPLAY_CHANNEL, SpiceDisplayChannel)) +#define SPICE_DISPLAY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_DISPLAY_CHANNEL, SpiceDisplayChannelClass)) +#define SPICE_IS_DISPLAY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_DISPLAY_CHANNEL)) +#define SPICE_IS_DISPLAY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_DISPLAY_CHANNEL)) +#define SPICE_DISPLAY_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_DISPLAY_CHANNEL, SpiceDisplayChannelClass)) + +typedef struct _SpiceDisplayChannel SpiceDisplayChannel; +typedef struct _SpiceDisplayChannelClass SpiceDisplayChannelClass; +typedef struct _SpiceDisplayChannelPrivate SpiceDisplayChannelPrivate; + +#define SPICE_TYPE_GL_SCANOUT (spice_gl_scanout_get_type ()) + +/** + * SpiceGlScanout: + * @fd: a drm DMABUF file that can be imported with eglCreateImageKHR + * @width: width of the scanout + * @height: height of the scanout + * @stride: stride of the scanout + * @format: the drm fourcc format + * @y0top: orientation of the scanout + * + * Holds the information necessary for using the GL display scanout. + **/ +typedef struct _SpiceGlScanout SpiceGlScanout; +struct _SpiceGlScanout { + gint fd; + guint32 width; + guint32 height; + guint32 stride; + guint32 format; + gboolean y0top; +}; + +/** + * SpiceDisplayMonitorConfig: + * @id: monitor id + * @surface_id: monitor surface id + * @x: x position of the monitor + * @y: y position of the monitor + * @width: width of the monitor + * @height: height of the monitor + * + * Holds a monitor configuration. + **/ +typedef struct _SpiceDisplayMonitorConfig SpiceDisplayMonitorConfig; +struct _SpiceDisplayMonitorConfig { + guint id; + guint surface_id; + guint x; + guint y; + guint width; + guint height; +}; + +/** + * SpiceDisplayPrimary: + * @format: primary buffer format + * @width: width of the primary + * @height: height of the primary + * @stride: stride of the primary + * @shmid: identifier of the shared memory segment associated with + * the @data, or -1 if not shm + * @data: pointer to primary buffer + * @marked: whether the display is marked ready + * + * Holds the information necessary to use the primary surface. + **/ +typedef struct _SpiceDisplayPrimary SpiceDisplayPrimary; +struct _SpiceDisplayPrimary { + enum SpiceSurfaceFmt format; + gint width; + gint height; + gint stride; + gint shmid; + guint8 *data; + gboolean marked; +}; + +/** + * SpiceDisplayChannel: + * + * The #SpiceDisplayChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceDisplayChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceDisplayChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceDisplayChannelClass: + * @parent_class: Parent class. + * @display_primary_create: Signal class handler for the #SpiceDisplayChannel::display-primary-create signal. + * @display_primary_destroy: Signal class handler for the #SpiceDisplayChannel::display-primary-destroy signal. + * @display_invalidate: Signal class handler for the #SpiceDisplayChannel::display-invalidate signal. + * @display_mark: Signal class handler for the #SpiceDisplayChannel::display-mark signal. + * + * Class structure for #SpiceDisplayChannel. + */ +struct _SpiceDisplayChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*display_primary_create)(SpiceChannel *channel, gint format, + gint width, gint height, gint stride, + gint shmid, gpointer data); + void (*display_primary_destroy)(SpiceChannel *channel); + void (*display_invalidate)(SpiceChannel *channel, + gint x, gint y, gint w, gint h); + void (*display_mark)(SpiceChannel *channel, + gboolean mark); + + /*< private >*/ +}; + +GType spice_display_channel_get_type(void); +gboolean spice_display_get_primary(SpiceChannel *channel, guint32 surface_id, + SpiceDisplayPrimary *primary); + +void spice_display_change_preferred_compression(SpiceChannel *channel, gint compression); + +GType spice_gl_scanout_get_type (void) G_GNUC_CONST; +void spice_gl_scanout_free (SpiceGlScanout *scanout); + +const SpiceGlScanout* spice_display_get_gl_scanout(SpiceDisplayChannel *channel); +void spice_display_gl_draw_done(SpiceDisplayChannel *channel); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_DISPLAY_CHANNEL_H__ */ diff --git a/src/channel-inputs.c b/src/channel-inputs.c new file mode 100644 index 0000000..7572bff --- /dev/null +++ b/src/channel-inputs.c @@ -0,0 +1,603 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" + +/** + * SECTION:channel-inputs + * @short_description: control the server mouse and keyboard + * @title: Inputs Channel + * @section_id: + * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client.h + * + * Spice supports sending keyboard key events and keyboard leds + * synchronization. The key events are sent using + * spice_inputs_key_press() and spice_inputs_key_release() using + * a modified variant of PC XT scancodes. + * + * Guest keyboard leds state can be manipulated with + * spice_inputs_set_key_locks(). When key lock change, a notification + * is emitted with #SpiceInputsChannel::inputs-modifiers signal. + */ + +#define SPICE_INPUTS_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_INPUTS_CHANNEL, SpiceInputsChannelPrivate)) + +struct _SpiceInputsChannelPrivate { + int bs; + int dx, dy; + unsigned int x, y, dpy; + int motion_count; + int modifiers; + guint32 locks; +}; + +G_DEFINE_TYPE(SpiceInputsChannel, spice_inputs_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_KEY_MODIFIERS, +}; + +/* Signals */ +enum { + SPICE_INPUTS_MODIFIERS, + + SPICE_INPUTS_LAST_SIGNAL, +}; + +static guint signals[SPICE_INPUTS_LAST_SIGNAL]; + +static void spice_inputs_channel_up(SpiceChannel *channel); +static void spice_inputs_channel_reset(SpiceChannel *channel, gboolean migrating); +static void channel_set_handlers(SpiceChannelClass *klass); + +/* ------------------------------------------------------------------ */ + +static void spice_inputs_channel_init(SpiceInputsChannel *channel) +{ + channel->priv = SPICE_INPUTS_CHANNEL_GET_PRIVATE(channel); +} + +static void spice_inputs_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(object)->priv; + + switch (prop_id) { + case PROP_KEY_MODIFIERS: + g_value_set_int(value, c->modifiers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void spice_inputs_channel_finalize(GObject *obj) +{ + if (G_OBJECT_CLASS(spice_inputs_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_inputs_channel_parent_class)->finalize(obj); +} + +static void spice_inputs_channel_class_init(SpiceInputsChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_inputs_channel_finalize; + gobject_class->get_property = spice_inputs_get_property; + channel_class->channel_up = spice_inputs_channel_up; + channel_class->channel_reset = spice_inputs_channel_reset; + + g_object_class_install_property + (gobject_class, PROP_KEY_MODIFIERS, + g_param_spec_int("key-modifiers", + "Key modifiers", + "Guest keyboard lock/led state", + 0, INT_MAX, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * SpiceInputsChannel::inputs-modifiers: + * @display: the #SpiceInputsChannel that emitted the signal + * + * The #SpiceInputsChannel::inputs-modifiers signal is emitted when + * the guest keyboard locks are changed. You can read the current + * state from #SpiceInputsChannel:key-modifiers property. + **/ + /* TODO: use notify instead? */ + signals[SPICE_INPUTS_MODIFIERS] = + g_signal_new("inputs-modifiers", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceInputsChannelClass, inputs_modifiers), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private(klass, sizeof(SpiceInputsChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* ------------------------------------------------------------------ */ + +static SpiceMsgOut* mouse_motion(SpiceInputsChannel *channel) +{ + SpiceInputsChannelPrivate *c = channel->priv; + SpiceMsgcMouseMotion motion; + SpiceMsgOut *msg; + + if (!c->dx && !c->dy) + return NULL; + + motion.buttons_state = c->bs; + motion.dx = c->dx; + motion.dy = c->dy; + msg = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_INPUTS_MOUSE_MOTION); + msg->marshallers->msgc_inputs_mouse_motion(msg->marshaller, &motion); + + c->motion_count++; + c->dx = 0; + c->dy = 0; + + return msg; +} + +static SpiceMsgOut* mouse_position(SpiceInputsChannel *channel) +{ + SpiceInputsChannelPrivate *c = channel->priv; + SpiceMsgcMousePosition position; + SpiceMsgOut *msg; + + if (c->dpy == -1) + return NULL; + + /* CHANNEL_DEBUG(channel, "%s: +%d+%d", __FUNCTION__, c->x, c->y); */ + position.buttons_state = c->bs; + position.x = c->x; + position.y = c->y; + position.display_id = c->dpy; + msg = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_INPUTS_MOUSE_POSITION); + msg->marshallers->msgc_inputs_mouse_position(msg->marshaller, &position); + + c->motion_count++; + c->dpy = -1; + + return msg; +} + +/* main context */ +static void send_position(SpiceInputsChannel *channel) +{ + SpiceMsgOut *msg; + + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + msg = mouse_position(channel); + if (!msg) /* if no motion */ + return; + + spice_msg_out_send(msg); +} + +/* main context */ +static void send_motion(SpiceInputsChannel *channel) +{ + SpiceMsgOut *msg; + + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + msg = mouse_motion(channel); + if (!msg) /* if no motion */ + return; + + spice_msg_out_send(msg); +} + +/* coroutine context */ +static void inputs_handle_init(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv; + SpiceMsgInputsInit *init = spice_msg_in_parsed(in); + + c->modifiers = init->keyboard_modifiers; + g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0); +} + +/* coroutine context */ +static void inputs_handle_modifiers(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv; + SpiceMsgInputsKeyModifiers *modifiers = spice_msg_in_parsed(in); + + c->modifiers = modifiers->modifiers; + g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0); +} + +/* coroutine context */ +static void inputs_handle_ack(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv; + SpiceMsgOut *msg; + + c->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH; + + msg = mouse_motion(SPICE_INPUTS_CHANNEL(channel)); + if (msg) { /* if no motion, msg == NULL */ + spice_msg_out_send_internal(msg); + } + + msg = mouse_position(SPICE_INPUTS_CHANNEL(channel)); + if (msg) { + spice_msg_out_send_internal(msg); + } +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_INPUTS_INIT ] = inputs_handle_init, + [ SPICE_MSG_INPUTS_KEY_MODIFIERS ] = inputs_handle_modifiers, + [ SPICE_MSG_INPUTS_MOUSE_MOTION_ACK ] = inputs_handle_ack, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +/** + * spice_inputs_motion: + * @channel: a #SpiceInputsChannel + * @dx: delta X mouse coordinates + * @dy: delta Y mouse coordinates + * @button_state: SPICE_MOUSE_BUTTON_MASK flags + * + * Change mouse position (used in SPICE_MOUSE_MODE_CLIENT). + **/ +void spice_inputs_motion(SpiceInputsChannel *channel, gint dx, gint dy, + gint button_state) +{ + SpiceInputsChannelPrivate *c; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_UNCONNECTED); + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + + if (dx == 0 && dy == 0) + return; + + c = channel->priv; + c->bs = button_state; + c->dx += dx; + c->dy += dy; + + if (c->motion_count < SPICE_INPUT_MOTION_ACK_BUNCH * 2) { + send_motion(channel); + } +} + +/** + * spice_inputs_position: + * @channel: a #SpiceInputsChannel + * @x: X mouse coordinates + * @y: Y mouse coordinates + * @display: display channel id + * @button_state: SPICE_MOUSE_BUTTON_MASK flags + * + * Change mouse position (used in SPICE_MOUSE_MODE_CLIENT). + **/ +void spice_inputs_position(SpiceInputsChannel *channel, gint x, gint y, + gint display, gint button_state) +{ + SpiceInputsChannelPrivate *c; + + g_return_if_fail(channel != NULL); + + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + + c = channel->priv; + c->bs = button_state; + c->x = x; + c->y = y; + c->dpy = display; + + if (c->motion_count < SPICE_INPUT_MOTION_ACK_BUNCH * 2) { + send_position(channel); + } else { + CHANNEL_DEBUG(channel, "over SPICE_INPUT_MOTION_ACK_BUNCH * 2, dropping"); + } +} + +/** + * spice_inputs_button_press: + * @channel: a #SpiceInputsChannel + * @button: a SPICE_MOUSE_BUTTON + * @button_state: SPICE_MOUSE_BUTTON_MASK flags + * + * Press a mouse button. + **/ +void spice_inputs_button_press(SpiceInputsChannel *channel, gint button, + gint button_state) +{ + SpiceInputsChannelPrivate *c; + SpiceMsgcMousePress press; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + c = channel->priv; + switch (button) { + case SPICE_MOUSE_BUTTON_LEFT: + button_state |= SPICE_MOUSE_BUTTON_MASK_LEFT; + break; + case SPICE_MOUSE_BUTTON_MIDDLE: + button_state |= SPICE_MOUSE_BUTTON_MASK_MIDDLE; + break; + case SPICE_MOUSE_BUTTON_RIGHT: + button_state |= SPICE_MOUSE_BUTTON_MASK_RIGHT; + break; + } + + c->bs = button_state; + send_motion(channel); + send_position(channel); + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_INPUTS_MOUSE_PRESS); + press.button = button; + press.buttons_state = button_state; + msg->marshallers->msgc_inputs_mouse_press(msg->marshaller, &press); + spice_msg_out_send(msg); +} + +/** + * spice_inputs_button_release: + * @channel: a #SpiceInputsChannel + * @button: a SPICE_MOUSE_BUTTON + * @button_state: SPICE_MOUSE_BUTTON_MASK flags + * + * Release a button. + **/ +void spice_inputs_button_release(SpiceInputsChannel *channel, gint button, + gint button_state) +{ + SpiceInputsChannelPrivate *c; + SpiceMsgcMouseRelease release; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + c = channel->priv; + switch (button) { + case SPICE_MOUSE_BUTTON_LEFT: + button_state &= ~SPICE_MOUSE_BUTTON_MASK_LEFT; + break; + case SPICE_MOUSE_BUTTON_MIDDLE: + button_state &= ~SPICE_MOUSE_BUTTON_MASK_MIDDLE; + break; + case SPICE_MOUSE_BUTTON_RIGHT: + button_state &= ~SPICE_MOUSE_BUTTON_MASK_RIGHT; + break; + } + + c->bs = button_state; + send_motion(channel); + send_position(channel); + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_INPUTS_MOUSE_RELEASE); + release.button = button; + release.buttons_state = button_state; + msg->marshallers->msgc_inputs_mouse_release(msg->marshaller, &release); + spice_msg_out_send(msg); +} + +/** + * spice_inputs_key_press: + * @channel: a #SpiceInputsChannel + * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0 + * prefix, drop the prefix and OR the scancode with %0x100. + * + * Press a key. + **/ +void spice_inputs_key_press(SpiceInputsChannel *channel, guint scancode) +{ + SpiceMsgcKeyDown down; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_UNCONNECTED); + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + down.code = spice_make_scancode(scancode, FALSE); + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_INPUTS_KEY_DOWN); + msg->marshallers->msgc_inputs_key_down(msg->marshaller, &down); + spice_msg_out_send(msg); +} + +/** + * spice_inputs_key_release: + * @channel: a #SpiceInputsChannel + * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0 + * prefix, drop the prefix and OR the scancode with %0x100. + * + * Release a key. + **/ +void spice_inputs_key_release(SpiceInputsChannel *channel, guint scancode) +{ + SpiceMsgcKeyUp up; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_UNCONNECTED); + if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY) + return; + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + up.code = spice_make_scancode(scancode, TRUE); + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_INPUTS_KEY_UP); + msg->marshallers->msgc_inputs_key_up(msg->marshaller, &up); + spice_msg_out_send(msg); +} + +/** + * spice_inputs_key_press_and_release: + * @channel: a #SpiceInputsChannel + * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0 + * prefix, drop the prefix and OR the scancode with %0x100. + * + * Press and release a key event atomically (in the same message). + * + * Since: 0.13 + **/ +void spice_inputs_key_press_and_release(SpiceInputsChannel *input_channel, guint scancode) +{ + SpiceChannel *channel = SPICE_CHANNEL(input_channel); + + g_return_if_fail(channel != NULL); + g_return_if_fail(channel->priv->state != SPICE_CHANNEL_STATE_UNCONNECTED); + + if (channel->priv->state != SPICE_CHANNEL_STATE_READY) + return; + if (spice_channel_get_read_only(channel)) + return; + + if (spice_channel_test_capability(channel, SPICE_INPUTS_CAP_KEY_SCANCODE)) { + SpiceMsgOut *msg; + guint16 code; + guint8 *buf; + + msg = spice_msg_out_new(channel, SPICE_MSGC_INPUTS_KEY_SCANCODE); + if (scancode < 0x100) { + buf = (guint8*)spice_marshaller_reserve_space(msg->marshaller, 2); + buf[0] = spice_make_scancode(scancode, FALSE); + buf[1] = spice_make_scancode(scancode, TRUE); + } else { + buf = (guint8*)spice_marshaller_reserve_space(msg->marshaller, 4); + code = spice_make_scancode(scancode, FALSE); + buf[0] = code & 0xff; + buf[1] = code >> 8; + code = spice_make_scancode(scancode, TRUE); + buf[2] = code & 0xff; + buf[3] = code >> 8; + } + spice_msg_out_send(msg); + } else { + CHANNEL_DEBUG(channel, "The server doesn't support atomic press and release"); + spice_inputs_key_press(input_channel, scancode); + spice_inputs_key_release(input_channel, scancode); + } +} + +/* main or coroutine context */ +static SpiceMsgOut* set_key_locks(SpiceInputsChannel *channel, guint locks) +{ + SpiceMsgcKeyModifiers modifiers; + SpiceMsgOut *msg; + SpiceInputsChannelPrivate *ic; + SpiceChannelPrivate *c; + + g_return_val_if_fail(SPICE_IS_INPUTS_CHANNEL(channel), NULL); + + ic = channel->priv; + c = SPICE_CHANNEL(channel)->priv; + + ic->locks = locks; + if (c->state != SPICE_CHANNEL_STATE_READY) + return NULL; + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_INPUTS_KEY_MODIFIERS); + modifiers.modifiers = locks; + msg->marshallers->msgc_inputs_key_modifiers(msg->marshaller, &modifiers); + return msg; +} + +/** + * spice_inputs_set_key_locks: + * @channel: a #SpiceInputsChannel + * @locks: #SpiceInputsLock modifiers flags + * + * Set the keyboard locks on the guest (Caps, Num, Scroll..) + **/ +void spice_inputs_set_key_locks(SpiceInputsChannel *channel, guint locks) +{ + SpiceMsgOut *msg; + + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + msg = set_key_locks(channel, locks); + if (!msg) /* you can set_key_locks() even if the channel is not ready */ + return; + + spice_msg_out_send(msg); /* main -> coroutine */ +} + +/* coroutine context */ +static void spice_inputs_channel_up(SpiceChannel *channel) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv; + SpiceMsgOut *msg; + + if (spice_channel_get_read_only(channel)) + return; + + msg = set_key_locks(SPICE_INPUTS_CHANNEL(channel), c->locks); + spice_msg_out_send_internal(msg); +} + +static void spice_inputs_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv; + c->motion_count = 0; + + SPICE_CHANNEL_CLASS(spice_inputs_channel_parent_class)->channel_reset(channel, migrating); +} diff --git a/src/channel-inputs.h b/src/channel-inputs.h new file mode 100644 index 0000000..5123c47 --- /dev/null +++ b/src/channel-inputs.h @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_INPUTS_CHANNEL_H__ +#define __SPICE_CLIENT_INPUTS_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_INPUTS_CHANNEL (spice_inputs_channel_get_type()) +#define SPICE_INPUTS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_INPUTS_CHANNEL, SpiceInputsChannel)) +#define SPICE_INPUTS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_INPUTS_CHANNEL, SpiceInputsChannelClass)) +#define SPICE_IS_INPUTS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_INPUTS_CHANNEL)) +#define SPICE_IS_INPUTS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_INPUTS_CHANNEL)) +#define SPICE_INPUTS_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_INPUTS_CHANNEL, SpiceInputsChannelClass)) + +typedef struct _SpiceInputsChannel SpiceInputsChannel; +typedef struct _SpiceInputsChannelClass SpiceInputsChannelClass; +typedef struct _SpiceInputsChannelPrivate SpiceInputsChannelPrivate; + +/** + * SpiceInputsLock: + * @SPICE_INPUTS_SCROLL_LOCK: Scroll Lock + * @SPICE_INPUTS_NUM_LOCK: Num Lock + * @SPICE_INPUTS_CAPS_LOCK: Caps Lock + * + * Constants used to synchronize modifiers between a client and a guest. + **/ +typedef enum { + SPICE_INPUTS_SCROLL_LOCK = (1 << 0), + SPICE_INPUTS_NUM_LOCK = (1 << 1), + SPICE_INPUTS_CAPS_LOCK = (1 << 2) +} SpiceInputsLock; + +/** + * SpiceInputsChannel: + * + * The #SpiceInputsChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceInputsChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceInputsChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceInputsChannelClass: + * @parent_class: Parent class. + * @inputs_modifiers: Signal class handler for the #SpiceInputsChannel::inputs-modifiers signal. + * + * Class structure for #SpiceInputsChannel. + */ +struct _SpiceInputsChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*inputs_modifiers)(SpiceChannel *channel); + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_inputs_channel_get_type(void); + +void spice_inputs_motion(SpiceInputsChannel *channel, gint dx, gint dy, + gint button_state); +void spice_inputs_position(SpiceInputsChannel *channel, gint x, gint y, + gint display, gint button_state); +void spice_inputs_button_press(SpiceInputsChannel *channel, gint button, + gint button_state); +void spice_inputs_button_release(SpiceInputsChannel *channel, gint button, + gint button_state); +void spice_inputs_key_press(SpiceInputsChannel *channel, guint scancode); +void spice_inputs_key_release(SpiceInputsChannel *channel, guint scancode); +void spice_inputs_set_key_locks(SpiceInputsChannel *channel, guint locks); +void spice_inputs_key_press_and_release(SpiceInputsChannel *channel, guint scancode); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_INPUTS_CHANNEL_H__ */ diff --git a/src/channel-main.c b/src/channel-main.c new file mode 100644 index 0000000..3d6ac2f --- /dev/null +++ b/src/channel-main.c @@ -0,0 +1,3496 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#include + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-marshal.h" + +#include "spice-util-priv.h" +#include "spice-channel-priv.h" +#include "spice-session-priv.h" +#include "spice-audio-priv.h" +#include "spice-file-transfer-task.h" + +/** + * SECTION:channel-main + * @short_description: the main Spice channel + * @title: Main Channel + * @section_id: + * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client.h + * + * The main channel is the Spice session control channel. It handles + * communication initialization (channels list), migrations, mouse + * modes, multimedia time, and agent communication. + * + * + */ + +#define SPICE_MAIN_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_MAIN_CHANNEL, SpiceMainChannelPrivate)) + +#define MAX_DISPLAY 16 /* Note must fit in a guint32, see monitors_align */ + +typedef struct spice_migrate spice_migrate; + +/** + * SECTION:file-transfer-task + * @short_description: Monitoring file transfers + * @title: File Transfer Task + * @section_id: + * @see_also: #SpiceMainChannel + * @stability: Stable + * @include: spice-client.h + * + * SpiceFileTransferTask is an object that represents a particular file + * transfer between the client and the guest. The properties and signals of the + * object can be used to monitor the status and result of the transfer. The + * Main Channel's #SpiceMainChannel::new-file-transfer signal will be emitted + * whenever a new file transfer task is initiated. + * + * Since: 0.31 + */ + +struct _SpiceFileTransferTask +{ + GObject parent; + + uint32_t id; + gboolean pending; + GFile *file; + SpiceMainChannel *channel; + GFileInputStream *file_stream; + GFileCopyFlags flags; + GCancellable *cancellable; + GFileProgressCallback progress_callback; + gpointer progress_callback_data; + GAsyncReadyCallback callback; + gpointer user_data; + char *buffer; + uint64_t read_bytes; + uint64_t file_size; + gint64 start_time; + gint64 last_update; + GError *error; +}; + +struct _SpiceFileTransferTaskClass +{ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE(SpiceFileTransferTask, spice_file_transfer_task, G_TYPE_OBJECT) + +#define FILE_XFER_CHUNK_SIZE (VD_AGENT_MAX_DATA_SIZE * 32) + +enum { + PROP_TASK_ID = 1, + PROP_TASK_CHANNEL, + PROP_TASK_CANCELLABLE, + PROP_TASK_FILE, + PROP_TASK_PROGRESS, +}; + +enum { + SIGNAL_FINISHED, + LAST_TASK_SIGNAL +}; + +static guint task_signals[LAST_TASK_SIGNAL]; + +typedef enum { + DISPLAY_UNDEFINED, + DISPLAY_DISABLED, + DISPLAY_ENABLED, +} SpiceDisplayState; + +typedef struct { + int x; + int y; + int width; + int height; + SpiceDisplayState display_state; +} SpiceDisplayConfig; + +struct _SpiceMainChannelPrivate { + enum SpiceMouseMode mouse_mode; + enum SpiceMouseMode requested_mouse_mode; + bool agent_connected; + bool agent_caps_received; + + gboolean agent_display_config_sent; + guint8 display_color_depth; + gboolean display_disable_wallpaper:1; + gboolean display_disable_font_smooth:1; + gboolean display_disable_animation:1; + gboolean disable_display_position:1; + gboolean disable_display_align:1; + + int agent_tokens; + VDAgentMessage agent_msg; /* partial msg reconstruction */ + guint8 *agent_msg_data; + guint agent_msg_pos; + uint8_t agent_msg_size; + uint32_t agent_caps[VD_AGENT_CAPS_SIZE]; + SpiceDisplayConfig display[MAX_DISPLAY]; + gint timer_id; + GQueue *agent_msg_queue; + GHashTable *file_xfer_tasks; + GHashTable *flushing; + + guint switch_host_delayed_id; + guint migrate_delayed_id; + spice_migrate *migrate_data; + int max_clipboard; + + gboolean agent_volume_playback_sync; + gboolean agent_volume_record_sync; + GCancellable *cancellable_volume_info; +}; + +struct spice_migrate { + struct coroutine *from; + SpiceMigrationDstInfo *info; + SpiceSession *session; + guint nchannels; + SpiceChannel *src_channel; + SpiceChannel *dst_channel; + bool do_seamless; /* used as input and output for the seamless migration handshake. + input: whether to send to the dest SPICE_MSGC_MAIN_MIGRATE_DST_DO_SEAMLESS + output: whether the dest approved seamless migration + (SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK/NACK) + */ + uint32_t src_mig_version; +}; + +G_DEFINE_TYPE(SpiceMainChannel, spice_main_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_MOUSE_MODE, + PROP_AGENT_CONNECTED, + PROP_AGENT_CAPS_0, + PROP_DISPLAY_DISABLE_WALLPAPER, + PROP_DISPLAY_DISABLE_FONT_SMOOTH, + PROP_DISPLAY_DISABLE_ANIMATION, + PROP_DISPLAY_COLOR_DEPTH, + PROP_DISABLE_DISPLAY_POSITION, + PROP_DISABLE_DISPLAY_ALIGN, + PROP_MAX_CLIPBOARD, +}; + +/* Signals */ +enum { + SPICE_MAIN_MOUSE_UPDATE, + SPICE_MAIN_AGENT_UPDATE, + SPICE_MAIN_CLIPBOARD, + SPICE_MAIN_CLIPBOARD_GRAB, + SPICE_MAIN_CLIPBOARD_REQUEST, + SPICE_MAIN_CLIPBOARD_RELEASE, + SPICE_MAIN_CLIPBOARD_SELECTION, + SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, + SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, + SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, + SPICE_MIGRATION_STARTED, + SPICE_MAIN_NEW_FILE_TRANSFER, + SPICE_MAIN_LAST_SIGNAL, +}; + +static guint signals[SPICE_MAIN_LAST_SIGNAL]; + +static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg); +static void channel_set_handlers(SpiceChannelClass *klass); +static void agent_send_msg_queue(SpiceMainChannel *channel); +static void agent_free_msg_queue(SpiceMainChannel *channel); +static void migrate_channel_event_cb(SpiceChannel *channel, SpiceChannelEvent event, + gpointer data); +static gboolean main_migrate_handshake_done(gpointer data); +static void spice_main_channel_send_migration_handshake(SpiceChannel *channel); +static void file_xfer_continue_read(SpiceFileTransferTask *task); +static void spice_file_transfer_task_completed(SpiceFileTransferTask *self, GError *error); +static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success); +static void spice_main_set_max_clipboard(SpiceMainChannel *self, gint max); +static void set_agent_connected(SpiceMainChannel *channel, gboolean connected); + +/* ------------------------------------------------------------------ */ + +static const char *agent_msg_types[] = { + [ VD_AGENT_MOUSE_STATE ] = "mouse state", + [ VD_AGENT_MONITORS_CONFIG ] = "monitors config", + [ VD_AGENT_REPLY ] = "reply", + [ VD_AGENT_CLIPBOARD ] = "clipboard", + [ VD_AGENT_DISPLAY_CONFIG ] = "display config", + [ VD_AGENT_ANNOUNCE_CAPABILITIES ] = "announce caps", + [ VD_AGENT_CLIPBOARD_GRAB ] = "clipboard grab", + [ VD_AGENT_CLIPBOARD_REQUEST ] = "clipboard request", + [ VD_AGENT_CLIPBOARD_RELEASE ] = "clipboard release", + [ VD_AGENT_AUDIO_VOLUME_SYNC ] = "volume-sync", +}; + +static const char *agent_caps[] = { + [ VD_AGENT_CAP_MOUSE_STATE ] = "mouse state", + [ VD_AGENT_CAP_MONITORS_CONFIG ] = "monitors config", + [ VD_AGENT_CAP_REPLY ] = "reply", + [ VD_AGENT_CAP_CLIPBOARD ] = "clipboard (old)", + [ VD_AGENT_CAP_DISPLAY_CONFIG ] = "display config", + [ VD_AGENT_CAP_CLIPBOARD_BY_DEMAND ] = "clipboard", + [ VD_AGENT_CAP_CLIPBOARD_SELECTION ] = "clipboard selection", + [ VD_AGENT_CAP_SPARSE_MONITORS_CONFIG ] = "sparse monitors", + [ VD_AGENT_CAP_GUEST_LINEEND_LF ] = "line-end lf", + [ VD_AGENT_CAP_GUEST_LINEEND_CRLF ] = "line-end crlf", + [ VD_AGENT_CAP_MAX_CLIPBOARD ] = "max-clipboard", + [ VD_AGENT_CAP_AUDIO_VOLUME_SYNC ] = "volume-sync", + [ VD_AGENT_CAP_MONITORS_CONFIG_POSITION ] = "monitors config position", +}; +#define NAME(_a, _i) ((_i) < SPICE_N_ELEMENTS(_a) ? (_a[(_i)] ?: "?") : "?") + +/* ------------------------------------------------------------------ */ + +static gboolean test_agent_cap(SpiceMainChannel *channel, guint32 cap) +{ + SpiceMainChannelPrivate *c = channel->priv; + + if (!c->agent_caps_received) + return FALSE; + + return VD_AGENT_HAS_CAPABILITY(c->agent_caps, G_N_ELEMENTS(c->agent_caps), cap); +} + +static void spice_main_channel_reset_capabilties(SpiceChannel *channel) +{ + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_MAIN_CAP_NAME_AND_UUID); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_MAIN_CAP_SEAMLESS_MIGRATE); +} + +static void spice_main_channel_init(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c; + + c = channel->priv = SPICE_MAIN_CHANNEL_GET_PRIVATE(channel); + c->agent_msg_queue = g_queue_new(); + c->file_xfer_tasks = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_object_unref); + c->flushing = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, + g_object_unref); + c->cancellable_volume_info = g_cancellable_new(); + + spice_main_channel_reset_capabilties(SPICE_CHANNEL(channel)); + c->requested_mouse_mode = SPICE_MOUSE_MODE_CLIENT; +} + +static gint spice_main_get_max_clipboard(SpiceMainChannel *self) +{ + g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(self), 0); + + if (g_getenv("SPICE_MAX_CLIPBOARD")) + return atoi(g_getenv("SPICE_MAX_CLIPBOARD")); + + return self->priv->max_clipboard; +} + +static void spice_main_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object); + SpiceMainChannelPrivate *c = self->priv; + + switch (prop_id) { + case PROP_MOUSE_MODE: + g_value_set_int(value, c->mouse_mode); + break; + case PROP_AGENT_CONNECTED: + g_value_set_boolean(value, c->agent_connected); + break; + case PROP_AGENT_CAPS_0: + g_value_set_int(value, c->agent_caps[0]); + break; + case PROP_DISPLAY_DISABLE_WALLPAPER: + g_value_set_boolean(value, c->display_disable_wallpaper); + break; + case PROP_DISPLAY_DISABLE_FONT_SMOOTH: + g_value_set_boolean(value, c->display_disable_font_smooth); + break; + case PROP_DISPLAY_DISABLE_ANIMATION: + g_value_set_boolean(value, c->display_disable_animation); + break; + case PROP_DISPLAY_COLOR_DEPTH: + g_value_set_uint(value, c->display_color_depth); + break; + case PROP_DISABLE_DISPLAY_POSITION: + g_value_set_boolean(value, c->disable_display_position); + break; + case PROP_DISABLE_DISPLAY_ALIGN: + g_value_set_boolean(value, c->disable_display_align); + break; + case PROP_MAX_CLIPBOARD: + g_value_set_int(value, spice_main_get_max_clipboard(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void spice_main_set_property(GObject *gobject, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SpiceMainChannel *self = SPICE_MAIN_CHANNEL(gobject); + SpiceMainChannelPrivate *c = self->priv; + + switch (prop_id) { + case PROP_DISPLAY_DISABLE_WALLPAPER: + c->display_disable_wallpaper = g_value_get_boolean(value); + break; + case PROP_DISPLAY_DISABLE_FONT_SMOOTH: + c->display_disable_font_smooth = g_value_get_boolean(value); + break; + case PROP_DISPLAY_DISABLE_ANIMATION: + c->display_disable_animation = g_value_get_boolean(value); + break; + case PROP_DISPLAY_COLOR_DEPTH: { + guint color_depth = g_value_get_uint(value); + g_return_if_fail(color_depth % 8 == 0); + c->display_color_depth = color_depth; + break; + } + case PROP_DISABLE_DISPLAY_POSITION: + c->disable_display_position = g_value_get_boolean(value); + break; + case PROP_DISABLE_DISPLAY_ALIGN: + c->disable_display_align = g_value_get_boolean(value); + break; + case PROP_MAX_CLIPBOARD: + spice_main_set_max_clipboard(self, g_value_get_int(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_main_channel_dispose(GObject *obj) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv; + + if (c->timer_id) { + g_source_remove(c->timer_id); + c->timer_id = 0; + } + + if (c->switch_host_delayed_id) { + g_source_remove(c->switch_host_delayed_id); + c->switch_host_delayed_id = 0; + } + + if (c->migrate_delayed_id) { + g_source_remove(c->migrate_delayed_id); + c->migrate_delayed_id = 0; + } + + g_clear_pointer(&c->file_xfer_tasks, g_hash_table_unref); + g_clear_pointer (&c->flushing, g_hash_table_unref); + + g_cancellable_cancel(c->cancellable_volume_info); + g_clear_object(&c->cancellable_volume_info); + + if (G_OBJECT_CLASS(spice_main_channel_parent_class)->dispose) + G_OBJECT_CLASS(spice_main_channel_parent_class)->dispose(obj); +} + +static void spice_main_channel_finalize(GObject *obj) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv; + + g_free(c->agent_msg_data); + agent_free_msg_queue(SPICE_MAIN_CHANNEL(obj)); + + if (G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize(obj); +} + +/* coroutine context */ +static void spice_channel_iterate_write(SpiceChannel *channel) +{ + agent_send_msg_queue(SPICE_MAIN_CHANNEL(channel)); + + if (SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write) + SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write(channel); +} + +/* main or coroutine context */ +static void spice_main_channel_reset_agent(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + GError *error; + GList *tasks; + GList *l; + + c->agent_connected = FALSE; + c->agent_caps_received = FALSE; + c->agent_display_config_sent = FALSE; + c->agent_msg_pos = 0; + g_clear_pointer(&c->agent_msg_data, g_free); + c->agent_msg_size = 0; + + tasks = g_hash_table_get_values(c->file_xfer_tasks); + for (l = tasks; l != NULL; l = l->next) { + SpiceFileTransferTask *task = (SpiceFileTransferTask *)l->data; + + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Agent connection closed"); + spice_file_transfer_task_completed(task, error); + } + g_list_free(tasks); + file_xfer_flushed(channel, FALSE); +} + +/* main or coroutine context */ +static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + /* This is not part of reset_agent, since the spice-server expects any + pending multi-chunk messages to be completed by the client, even after + it has send an agent-disconnected msg as that is what the original + spicec did. Also see the TODO in server/reds.c reds_reset_vdp() */ + c->agent_tokens = 0; + agent_free_msg_queue(SPICE_MAIN_CHANNEL(channel)); + c->agent_msg_queue = g_queue_new(); + + c->agent_volume_playback_sync = FALSE; + c->agent_volume_record_sync = FALSE; + + set_agent_connected(SPICE_MAIN_CHANNEL(channel), FALSE); + + SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_main_constructed(GObject *object) +{ + SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object); + SpiceMainChannelPrivate *c = self->priv; + + /* update default value */ + c->max_clipboard = spice_main_get_max_clipboard(self); + + if (G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed) + G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed(object); +} + +static void spice_main_channel_class_init(SpiceMainChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->dispose = spice_main_channel_dispose; + gobject_class->finalize = spice_main_channel_finalize; + gobject_class->get_property = spice_main_get_property; + gobject_class->set_property = spice_main_set_property; + gobject_class->constructed = spice_main_constructed; + + channel_class->handle_msg = spice_main_handle_msg; + channel_class->iterate_write = spice_channel_iterate_write; + channel_class->channel_reset = spice_main_channel_reset; + channel_class->channel_reset_capabilities = spice_main_channel_reset_capabilties; + channel_class->channel_send_migration_handshake = spice_main_channel_send_migration_handshake; + + /** + * SpiceMainChannel:mouse-mode: + * + * Spice protocol specifies two mouse modes, client mode and + * server mode. In client mode (%SPICE_MOUSE_MODE_CLIENT), the + * affective mouse is the client side mouse: the client sends + * mouse position within the display and the server sends mouse + * shape messages. In server mode (%SPICE_MOUSE_MODE_SERVER), the + * client sends relative mouse movements and the server sends + * position and shape commands. + **/ + g_object_class_install_property + (gobject_class, PROP_MOUSE_MODE, + g_param_spec_int("mouse-mode", + "Mouse mode", + "Mouse mode", + 0, INT_MAX, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, PROP_AGENT_CONNECTED, + g_param_spec_boolean("agent-connected", + "Agent connected", + "Whether the agent is connected", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, PROP_AGENT_CAPS_0, + g_param_spec_int("agent-caps-0", + "Agent caps 0", + "Agent capability bits 0 -> 31", + 0, INT_MAX, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, PROP_DISPLAY_DISABLE_WALLPAPER, + g_param_spec_boolean("disable-wallpaper", + "Disable guest wallpaper", + "Disable guest wallpaper", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_DISPLAY_DISABLE_FONT_SMOOTH, + g_param_spec_boolean("disable-font-smooth", + "Disable guest font smooth", + "Disable guest font smoothing", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_DISPLAY_DISABLE_ANIMATION, + g_param_spec_boolean("disable-animation", + "Disable guest animations", + "Disable guest animations", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_DISABLE_DISPLAY_POSITION, + g_param_spec_boolean("disable-display-position", + "Disable display position", + "Disable using display position when setting monitor config", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_DISPLAY_COLOR_DEPTH, + g_param_spec_uint("color-depth", + "Color depth", + "Color depth", 0, 32, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceMainChannel:disable-display-align: + * + * Disable automatic horizontal display position alignment. + * + * Since: 0.13 + */ + g_object_class_install_property + (gobject_class, PROP_DISABLE_DISPLAY_ALIGN, + g_param_spec_boolean("disable-display-align", + "Disable display align", + "Disable display position alignment", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceMainChannel:max-clipboard: + * + * Maximum size of clipboard operations in bytes (default 100MB, + * -1 for unlimited size); + * + * Since: 0.22 + **/ + g_object_class_install_property + (gobject_class, PROP_MAX_CLIPBOARD, + g_param_spec_int("max-clipboard", + "max clipboard", + "Maximum clipboard data size", + -1, G_MAXINT, 100 * 1024 * 1024, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /* TODO use notify instead */ + /** + * SpiceMainChannel::main-mouse-update: + * @main: the #SpiceMainChannel that emitted the signal + * + * Notify when the mouse mode has changed. + **/ + signals[SPICE_MAIN_MOUSE_UPDATE] = + g_signal_new("main-mouse-update", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceMainChannelClass, mouse_update), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /* TODO use notify instead */ + /** + * SpiceMainChannel::main-agent-update: + * @main: the #SpiceMainChannel that emitted the signal + * + * Notify when the %SpiceMainChannel:agent-connected or + * %SpiceMainChannel:agent-caps-0 property change. + **/ + signals[SPICE_MAIN_AGENT_UPDATE] = + g_signal_new("main-agent-update", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceMainChannelClass, agent_update), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + /** + * SpiceMainChannel::main-clipboard: + * @main: the #SpiceMainChannel that emitted the signal + * @type: the VD_AGENT_CLIPBOARD data type + * @data: clipboard data + * @size: size of @data in bytes + * + * Provides guest clipboard data requested by spice_main_clipboard_request(). + * + * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection instead. + **/ + signals[SPICE_MAIN_CLIPBOARD] = + g_signal_new("main-clipboard", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + 0, + NULL, NULL, + g_cclosure_user_marshal_VOID__UINT_POINTER_UINT, + G_TYPE_NONE, + 3, + G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-selection: + * @main: the #SpiceMainChannel that emitted the signal + * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard + * @type: the VD_AGENT_CLIPBOARD data type + * @data: clipboard data + * @size: size of @data in bytes + * + * Informs that clipboard selection data are available. + * + * Since: 0.6 + **/ + signals[SPICE_MAIN_CLIPBOARD_SELECTION] = + g_signal_new("main-clipboard-selection", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_user_marshal_VOID__UINT_UINT_POINTER_UINT, + G_TYPE_NONE, + 4, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-grab: + * @main: the #SpiceMainChannel that emitted the signal + * @types: the VD_AGENT_CLIPBOARD data types + * @ntypes: the number of @types + * + * Inform when clipboard data is available from the guest, and for + * which @types. + * + * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection-grab instead. + **/ + signals[SPICE_MAIN_CLIPBOARD_GRAB] = + g_signal_new("main-clipboard-grab", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + 0, + NULL, NULL, + g_cclosure_user_marshal_BOOLEAN__POINTER_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_POINTER, G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-selection-grab: + * @main: the #SpiceMainChannel that emitted the signal + * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard + * @types: the VD_AGENT_CLIPBOARD data types + * @ntypes: the number of @types + * + * Inform when clipboard data is available from the guest, and for + * which @types. + * + * Since: 0.6 + **/ + signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB] = + g_signal_new("main-clipboard-selection-grab", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_user_marshal_BOOLEAN__UINT_POINTER_UINT, + G_TYPE_BOOLEAN, + 3, + G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-request: + * @main: the #SpiceMainChannel that emitted the signal + * @types: the VD_AGENT_CLIPBOARD request type + * + * Request clipboard data from the client. + * + * Return value: %TRUE if the request is successful + * + * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection-request instead. + **/ + signals[SPICE_MAIN_CLIPBOARD_REQUEST] = + g_signal_new("main-clipboard-request", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + 0, + NULL, NULL, + g_cclosure_user_marshal_BOOLEAN__UINT, + G_TYPE_BOOLEAN, + 1, + G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-selection-request: + * @main: the #SpiceMainChannel that emitted the signal + * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard + * @types: the VD_AGENT_CLIPBOARD request type + * + * Request clipboard data from the client. + * + * Return value: %TRUE if the request is successful + * + * Since: 0.6 + **/ + signals[SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST] = + g_signal_new("main-clipboard-selection-request", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_user_marshal_BOOLEAN__UINT_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_UINT, G_TYPE_UINT); + + /** + * SpiceMainChannel::main-clipboard-release: + * @main: the #SpiceMainChannel that emitted the signal + * + * Inform when the clipboard is released from the guest, when no + * clipboard data is available from the guest. + * + * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection-release instead. + **/ + signals[SPICE_MAIN_CLIPBOARD_RELEASE] = + g_signal_new("main-clipboard-release", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * SpiceMainChannel::main-clipboard-selection-release: + * @main: the #SpiceMainChannel that emitted the signal + * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard + * + * Inform when the clipboard is released from the guest, when no + * clipboard data is available from the guest. + * + * Since: 0.6 + **/ + signals[SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE] = + g_signal_new("main-clipboard-selection-release", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, + G_TYPE_UINT); + + /** + * SpiceMainChannel::migration-started: + * @main: the #SpiceMainChannel that emitted the signal + * @session: a migration #SpiceSession + * + * Inform when migration is starting. Application wishing to make + * connections themself can set the #SpiceSession:client-sockets + * to @TRUE, then follow #SpiceSession::channel-new creation, and + * use spice_channel_open_fd() once the socket is created. + * + **/ + signals[SPICE_MIGRATION_STARTED] = + g_signal_new("migration-started", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + /** + * SpiceMainChannel::new-file-transfer: + * @main: the #SpiceMainChannel that emitted the signal + * @task: a #SpiceFileTransferTask + * + * This signal is emitted when a new file transfer task has been initiated + * on this channel. Client applications may take a reference on the @task + * object and use it to monitor the status of the file transfer task. + * + * Since: 0.31 + **/ + signals[SPICE_MAIN_NEW_FILE_TRANSFER] = + g_signal_new("new-file-transfer", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + g_type_class_add_private(klass, sizeof(SpiceMainChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* ------------------------------------------------------------------ */ + + +static void agent_free_msg_queue(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + + if (!c->agent_msg_queue) + return; + + while (!g_queue_is_empty(c->agent_msg_queue)) { + out = g_queue_pop_head(c->agent_msg_queue); + spice_msg_out_unref(out); + } + + g_clear_pointer(&c->agent_msg_queue, g_queue_free); +} + +static gboolean flush_foreach_remove(gpointer key G_GNUC_UNUSED, + gpointer value, gpointer user_data) +{ + gboolean success = GPOINTER_TO_UINT(user_data); + GTask *result = value; + g_task_return_boolean(result, success); + + return TRUE; +} + +static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success) +{ + SpiceMainChannelPrivate *c = channel->priv; + g_hash_table_foreach_remove(c->flushing, flush_foreach_remove, + GUINT_TO_POINTER(success)); +} + +static void file_xfer_flush_async(SpiceMainChannel *channel, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) +{ + GTask *task; + SpiceMainChannelPrivate *c = channel->priv; + gboolean was_empty; + + task = g_task_new(channel, cancellable, callback, user_data); + + was_empty = g_queue_is_empty(c->agent_msg_queue); + if (was_empty) { + g_task_return_boolean(task, TRUE); + g_object_unref(task); + return; + } + + /* wait until the last message currently in the queue has been sent */ + g_hash_table_insert(c->flushing, g_queue_peek_tail(c->agent_msg_queue), task); +} + +static gboolean file_xfer_flush_finish(SpiceMainChannel *channel, GAsyncResult *result, + GError **error) +{ + GTask *task = G_TASK(result); + + g_return_val_if_fail(g_task_is_valid(result, channel), FALSE); + + return g_task_propagate_boolean(task, error); +} + +/* coroutine context */ +static void agent_send_msg_queue(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + + while (c->agent_tokens > 0 && + !g_queue_is_empty(c->agent_msg_queue)) { + GTask *task; + c->agent_tokens--; + out = g_queue_pop_head(c->agent_msg_queue); + spice_msg_out_send_internal(out); + + task = g_hash_table_lookup(c->flushing, out); + if (task) { + /* if there's a flush task waiting for this message, finish it */ + g_task_return_boolean(task, TRUE); + g_hash_table_remove(c->flushing, out); + } + } + if (g_queue_is_empty(c->agent_msg_queue) && + g_hash_table_size(c->flushing) != 0) { + g_warning("unexpected flush task in list, clearing"); + file_xfer_flushed(channel, TRUE); + } +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() + + expected arguments, pair of data/data_size to send terminated with NULL: + agent_msg_queue_many(main, VD_AGENT_..., + &foo, sizeof(Foo), + data, data_size, NULL); +*/ +G_GNUC_NULL_TERMINATED +static void agent_msg_queue_many(SpiceMainChannel *channel, int type, const void *data, ...) +{ + va_list args; + SpiceMainChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + VDAgentMessage msg; + guint8 *payload; + gsize paysize, s, mins, size = 0; + const guint8 *d; + + G_STATIC_ASSERT(VD_AGENT_MAX_DATA_SIZE > sizeof(VDAgentMessage)); + + va_start(args, data); + for (d = data; d != NULL; d = va_arg(args, void*)) { + size += va_arg(args, gsize); + } + va_end(args); + + msg.protocol = VD_AGENT_PROTOCOL; + msg.type = type; + msg.opaque = 0; + msg.size = size; + + paysize = MIN(VD_AGENT_MAX_DATA_SIZE, size + sizeof(VDAgentMessage)); + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_AGENT_DATA); + payload = spice_marshaller_reserve_space(out->marshaller, paysize); + memcpy(payload, &msg, sizeof(VDAgentMessage)); + payload += sizeof(VDAgentMessage); + paysize -= sizeof(VDAgentMessage); + if (paysize == 0) { + g_queue_push_tail(c->agent_msg_queue, out); + out = NULL; + } + + va_start(args, data); + for (d = data; size > 0; d = va_arg(args, void*)) { + s = va_arg(args, gsize); + while (s > 0) { + if (out == NULL) { + paysize = MIN(VD_AGENT_MAX_DATA_SIZE, size); + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_AGENT_DATA); + payload = spice_marshaller_reserve_space(out->marshaller, paysize); + } + mins = MIN(paysize, s); + memcpy(payload, d, mins); + d += mins; + payload += mins; + s -= mins; + size -= mins; + paysize -= mins; + if (paysize == 0) { + g_queue_push_tail(c->agent_msg_queue, out); + out = NULL; + } + } + } + va_end(args); + g_warn_if_fail(out == NULL); +} + +static int monitors_cmp(const void *p1, const void *p2, gpointer user_data) +{ + const VDAgentMonConfig *m1 = p1; + const VDAgentMonConfig *m2 = p2; + double d1 = sqrt(m1->x * m1->x + m1->y * m1->y); + double d2 = sqrt(m2->x * m2->x + m2->y * m2->y); + int diff = d1 - d2; + + return diff == 0 ? (char*)p1 - (char*)p2 : diff; +} + +static void monitors_align(VDAgentMonConfig *monitors, int nmonitors) +{ + gint i, j, x = 0; + guint32 used = 0; + VDAgentMonConfig *sorted_monitors; + + if (nmonitors == 0) + return; + + /* sort by distance from origin */ + sorted_monitors = g_memdup(monitors, nmonitors * sizeof(VDAgentMonConfig)); + g_qsort_with_data(sorted_monitors, nmonitors, sizeof(VDAgentMonConfig), monitors_cmp, NULL); + + /* super-KISS ltr alignment, feel free to improve */ + for (i = 0; i < nmonitors; i++) { + /* Find where this monitor is in the sorted order */ + for (j = 0; j < nmonitors; j++) { + /* Avoid using the same entry twice, this happens with older + virt-viewer versions which always set x and y to 0 */ + if (used & (1 << j)) + continue; + if (memcmp(&monitors[j], &sorted_monitors[i], + sizeof(VDAgentMonConfig)) == 0) + break; + } + used |= 1 << j; + monitors[j].x = x; + monitors[j].y = 0; + x += monitors[j].width; + if (monitors[j].width || monitors[j].height) + SPICE_DEBUG("#%d +%d+%d-%ux%u", j, monitors[j].x, monitors[j].y, + monitors[j].width, monitors[j].height); + } + g_free(sorted_monitors); +} + + +#define agent_msg_queue(Channel, Type, Size, Data) \ + agent_msg_queue_many((Channel), (Type), (Data), (Size), NULL) + +/** + * spice_main_send_monitor_config: + * @channel: a #SpiceMainChannel + * + * Send monitors configuration previously set with + * spice_main_set_display() and spice_main_set_display_enabled() + * + * Returns: %TRUE on success. + **/ +gboolean spice_main_send_monitor_config(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c; + VDAgentMonitorsConfig *mon; + int i, j, monitors; + size_t size; + + g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE); + c = channel->priv; + g_return_val_if_fail(c->agent_connected, FALSE); + + if (spice_main_agent_test_capability(channel, + VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) { + monitors = SPICE_N_ELEMENTS(c->display); + } else { + monitors = 0; + for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) { + if (c->display[i].display_state == DISPLAY_ENABLED) + monitors += 1; + } + } + + size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors; + mon = g_malloc0(size); + + mon->num_of_monitors = monitors; + if (c->disable_display_position == FALSE || + c->disable_display_align == FALSE) + mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS; + + CHANNEL_DEBUG(channel, "sending new monitors config to guest"); + j = 0; + for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) { + if (c->display[i].display_state != DISPLAY_ENABLED) { + if (spice_main_agent_test_capability(channel, + VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) + j++; + continue; + } + mon->monitors[j].depth = c->display_color_depth ? c->display_color_depth : 32; + mon->monitors[j].width = c->display[i].width; + mon->monitors[j].height = c->display[i].height; + mon->monitors[j].x = c->display[i].x; + mon->monitors[j].y = c->display[i].y; + CHANNEL_DEBUG(channel, "monitor #%d: %ux%u+%d+%d @ %u bpp", j, + mon->monitors[j].width, mon->monitors[j].height, + mon->monitors[j].x, mon->monitors[j].y, + mon->monitors[j].depth); + j++; + } + + if (c->disable_display_align == FALSE) + monitors_align(mon->monitors, mon->num_of_monitors); + + agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon); + g_free(mon); + + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); + if (c->timer_id != 0) { + g_source_remove(c->timer_id); + c->timer_id = 0; + } + + return TRUE; +} + +static SpiceAudio *spice_main_get_audio(const SpiceMainChannel *channel) +{ + return spice_audio_get(spice_channel_get_session(SPICE_CHANNEL(channel)), NULL); +} + +static void audio_playback_volume_info_cb(GObject *object, GAsyncResult *res, gpointer user_data) +{ + SpiceMainChannel *main_channel = user_data; + SpiceAudio *audio = spice_main_get_audio(main_channel); + VDAgentAudioVolumeSync *avs; + guint16 *volume; + guint8 nchannels; + gboolean mute, ret; + gsize array_size; + GError *error = NULL; + + ret = spice_audio_get_playback_volume_info_finish(audio, res, &mute, &nchannels, + &volume, &error); + if (ret == FALSE || volume == NULL || nchannels == 0) { + if (error != NULL) { + g_warning("Failed to get playback async volume info: %s", error->message); + g_error_free(error); + } else { + SPICE_DEBUG("Failed to get playback async volume info"); + } + main_channel->priv->agent_volume_playback_sync = FALSE; + return; + } + + array_size = sizeof(uint16_t) * nchannels; + avs = g_malloc0(sizeof(VDAgentAudioVolumeSync) + array_size); + avs->is_playback = TRUE; + avs->mute = mute; + avs->nchannels = nchannels; + memcpy(avs->volume, volume, array_size); + + SPICE_DEBUG("%s mute=%s nchannels=%u volume[0]=%u", + __func__, spice_yes_no(mute), nchannels, volume[0]); + g_free(volume); + agent_msg_queue(main_channel, VD_AGENT_AUDIO_VOLUME_SYNC, + sizeof(VDAgentAudioVolumeSync) + array_size, avs); + g_free (avs); +} + +static void agent_sync_audio_playback(SpiceMainChannel *main_channel) +{ + SpiceAudio *audio = spice_main_get_audio(main_channel); + SpiceMainChannelPrivate *c = main_channel->priv; + + if (audio == NULL || + !test_agent_cap(main_channel, VD_AGENT_CAP_AUDIO_VOLUME_SYNC) || + c->agent_volume_playback_sync == TRUE) { + SPICE_DEBUG("%s - is not going to sync audio with guest", __func__); + return; + } + /* only one per connection */ + g_cancellable_reset(c->cancellable_volume_info); + c->agent_volume_playback_sync = TRUE; + spice_audio_get_playback_volume_info_async(audio, c->cancellable_volume_info, main_channel, + audio_playback_volume_info_cb, main_channel); +} + +static void audio_record_volume_info_cb(GObject *object, GAsyncResult *res, gpointer user_data) +{ + SpiceMainChannel *main_channel = user_data; + SpiceAudio *audio = spice_main_get_audio(main_channel); + VDAgentAudioVolumeSync *avs; + guint16 *volume; + guint8 nchannels; + gboolean ret, mute; + gsize array_size; + GError *error = NULL; + + ret = spice_audio_get_record_volume_info_finish(audio, res, &mute, &nchannels, &volume, &error); + if (ret == FALSE || volume == NULL || nchannels == 0) { + if (error != NULL) { + g_warning("Failed to get record async volume info: %s", error->message); + g_error_free(error); + } else { + SPICE_DEBUG("Failed to get record async volume info"); + } + main_channel->priv->agent_volume_record_sync = FALSE; + return; + } + + array_size = sizeof(uint16_t) * nchannels; + avs = g_malloc0(sizeof(VDAgentAudioVolumeSync) + array_size); + avs->is_playback = FALSE; + avs->mute = mute; + avs->nchannels = nchannels; + memcpy(avs->volume, volume, array_size); + + SPICE_DEBUG("%s mute=%s nchannels=%u volume[0]=%u", + __func__, spice_yes_no(mute), nchannels, volume[0]); + g_free(volume); + agent_msg_queue(main_channel, VD_AGENT_AUDIO_VOLUME_SYNC, + sizeof(VDAgentAudioVolumeSync) + array_size, avs); + g_free (avs); +} + +static void agent_sync_audio_record(SpiceMainChannel *main_channel) +{ + SpiceAudio *audio = spice_main_get_audio(main_channel); + SpiceMainChannelPrivate *c = main_channel->priv; + + if (audio == NULL || + !test_agent_cap(main_channel, VD_AGENT_CAP_AUDIO_VOLUME_SYNC) || + c->agent_volume_record_sync == TRUE) { + SPICE_DEBUG("%s - is not going to sync audio with guest", __func__); + return; + } + /* only one per connection */ + g_cancellable_reset(c->cancellable_volume_info); + c->agent_volume_record_sync = TRUE; + spice_audio_get_record_volume_info_async(audio, c->cancellable_volume_info, main_channel, + audio_record_volume_info_cb, main_channel); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_display_config(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + VDAgentDisplayConfig config = { 0, }; + + if (c->display_disable_wallpaper) { + config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_WALLPAPER; + } + + if (c->display_disable_font_smooth) { + config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_FONT_SMOOTH; + } + + if (c->display_disable_animation) { + config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_ANIMATION; + } + + if (c->display_color_depth != 0) { + config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_SET_COLOR_DEPTH; + config.depth = c->display_color_depth; + } + + CHANNEL_DEBUG(channel, "display_config: flags: %u, depth: %u", config.flags, config.depth); + + agent_msg_queue(channel, VD_AGENT_DISPLAY_CONFIG, sizeof(VDAgentDisplayConfig), &config); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_announce_caps(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + VDAgentAnnounceCapabilities *caps; + size_t size; + + if (!c->agent_connected) + return; + + size = sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES; + caps = g_malloc0(size); + if (!c->agent_caps_received) + caps->request = 1; + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_DISPLAY_CONFIG); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG_POSITION); + + agent_msg_queue(channel, VD_AGENT_ANNOUNCE_CAPABILITIES, size, caps); + g_free(caps); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection, + guint32 *types, int ntypes) +{ + SpiceMainChannelPrivate *c = channel->priv; + guint8 *msg; + VDAgentClipboardGrab *grab; + size_t size; + int i; + + if (!c->agent_connected) + return; + + g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); + + size = sizeof(VDAgentClipboardGrab) + sizeof(uint32_t) * ntypes; + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + size += 4; + } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) { + CHANNEL_DEBUG(channel, "Ignoring clipboard grab"); + return; + } + + msg = g_alloca(size); + memset(msg, 0, size); + + grab = (VDAgentClipboardGrab *)msg; + + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msg[0] = selection; + grab = (VDAgentClipboardGrab *)(msg + 4); + } + + for (i = 0; i < ntypes; i++) { + grab->types[i] = types[i]; + } + + agent_msg_queue(channel, VD_AGENT_CLIPBOARD_GRAB, size, msg); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_clipboard_notify(SpiceMainChannel *self, guint selection, + guint32 type, const guchar *data, size_t size) +{ + SpiceMainChannelPrivate *c = self->priv; + VDAgentClipboard *cb; + guint8 *msg; + size_t msgsize; + gint max_clipboard = spice_main_get_max_clipboard(self); + + g_return_if_fail(c->agent_connected); + g_return_if_fail(test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); + g_return_if_fail(max_clipboard == -1 || size < max_clipboard); + + msgsize = sizeof(VDAgentClipboard); + if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msgsize += 4; + } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) { + CHANNEL_DEBUG(self, "Ignoring clipboard notify"); + return; + } + + msg = g_alloca(msgsize); + memset(msg, 0, msgsize); + + cb = (VDAgentClipboard *)msg; + + if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msg[0] = selection; + cb = (VDAgentClipboard *)(msg + 4); + } + + cb->type = type; + agent_msg_queue_many(self, VD_AGENT_CLIPBOARD, msg, msgsize, data, size, NULL); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_clipboard_request(SpiceMainChannel *channel, guint selection, guint32 type) +{ + SpiceMainChannelPrivate *c = channel->priv; + VDAgentClipboardRequest *request; + guint8 *msg; + size_t msgsize; + + g_return_if_fail(c->agent_connected); + g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); + + msgsize = sizeof(VDAgentClipboardRequest); + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msgsize += 4; + } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) { + SPICE_DEBUG("Ignoring clipboard request"); + return; + } + + msg = g_alloca(msgsize); + memset(msg, 0, msgsize); + + request = (VDAgentClipboardRequest *)msg; + + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msg[0] = selection; + request = (VDAgentClipboardRequest *)(msg + 4); + } + + request->type = type; + + agent_msg_queue(channel, VD_AGENT_CLIPBOARD_REQUEST, msgsize, msg); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_clipboard_release(SpiceMainChannel *channel, guint selection) +{ + SpiceMainChannelPrivate *c = channel->priv; + guint8 msg[4] = { 0, }; + guint8 msgsize = 0; + + g_return_if_fail(c->agent_connected); + g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); + + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + msg[0] = selection; + msgsize += 4; + } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) { + SPICE_DEBUG("Ignoring clipboard release"); + return; + } + + agent_msg_queue(channel, VD_AGENT_CLIPBOARD_RELEASE, msgsize, msg); +} + +static gboolean any_display_has_dimensions(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c; + guint i; + + g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE); + c = channel->priv; + + for (i = 0; i < MAX_DISPLAY; i++) { + if (c->display[i].width > 0 && c->display[i].height > 0) + return TRUE; + } + + return FALSE; +} + +/* main context*/ +static gboolean timer_set_display(gpointer data) +{ + SpiceMainChannel *channel = data; + SpiceMainChannelPrivate *c = channel->priv; + SpiceSession *session; + gint i; + + c->timer_id = 0; + if (!c->agent_connected) + return FALSE; + + if (!any_display_has_dimensions(channel)) { + SPICE_DEBUG("Not sending monitors config, at least one monitor must have dimensions"); + return FALSE; + } + + session = spice_channel_get_session(SPICE_CHANNEL(channel)); + + if (!spice_main_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) { + /* ensure we have an explicit monitor configuration at least for + number of display channels */ + for (i = 0; i < spice_session_get_n_display_channels(session); i++) + if (c->display[i].display_state == DISPLAY_UNDEFINED) { + SPICE_DEBUG("Not sending monitors config, missing monitors"); + return FALSE; + } + } + spice_main_send_monitor_config(channel); + + return FALSE; +} + +/* any context */ +static void update_display_timer(SpiceMainChannel *channel, guint seconds) +{ + SpiceMainChannelPrivate *c = channel->priv; + + if (c->timer_id) + g_source_remove(c->timer_id); + + if (seconds != 0) { + c->timer_id = g_timeout_add_seconds(seconds, timer_set_display, channel); + } else { + /* We need to special case 0, as we want the callback to fire as soon + * as possible. g_timeout_add_seconds(0) would set up a timer which would fire + * at the next second boundary, which might be nearly 1 full second later. + */ + c->timer_id = g_timeout_add(0, timer_set_display, channel); + } + +} + +/* coroutine context */ +static void set_agent_connected(SpiceMainChannel *channel, gboolean connected) +{ + SpiceMainChannelPrivate *c = channel->priv; + + SPICE_DEBUG("agent connected: %s", spice_yes_no(connected)); + if (connected != c->agent_connected) { + c->agent_connected = connected; + g_coroutine_object_notify(G_OBJECT(channel), "agent-connected"); + } + if (!connected) + spice_main_channel_reset_agent(SPICE_MAIN_CHANNEL(channel)); + + g_coroutine_signal_emit(channel, signals[SPICE_MAIN_AGENT_UPDATE], 0); +} + +/* coroutine context */ +static void agent_start(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + SpiceMsgcMainAgentStart agent_start = { + .num_tokens = ~0, + }; + SpiceMsgOut *out; + + c->agent_volume_playback_sync = FALSE; + c->agent_volume_record_sync = FALSE; + c->agent_caps_received = false; + set_agent_connected(channel, TRUE); + + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_AGENT_START); + out->marshallers->msgc_main_agent_start(out->marshaller, &agent_start); + spice_msg_out_send_internal(out); + + if (c->agent_connected) { + agent_announce_caps(channel); + agent_send_msg_queue(channel); + } +} + +/* coroutine context */ +static void agent_stopped(SpiceMainChannel *channel) +{ + set_agent_connected(channel, FALSE); +} + +/** + * spice_main_request_mouse_mode: + * @channel: a %SpiceMainChannel + * @mode: a SPICE_MOUSE_MODE + * + * Request a mouse mode to the server. The server may not be able to + * change the mouse mode, but spice-gtk will try to request it + * when possible. + * + * Since: 0.32 + **/ +void spice_main_request_mouse_mode(SpiceMainChannel *channel, int mode) +{ + SpiceMsgcMainMouseModeRequest req = { + .mode = mode, + }; + SpiceMsgOut *out; + SpiceMainChannelPrivate *c; + + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + c = channel->priv; + + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + CHANNEL_DEBUG(channel, "request mouse mode %d", mode); + c->requested_mouse_mode = mode; + + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST); + out->marshallers->msgc_main_mouse_mode_request(out->marshaller, &req); + spice_msg_out_send(out); +} + +/* coroutine context */ +static void set_mouse_mode(SpiceMainChannel *channel, uint32_t supported, uint32_t current) +{ + SpiceMainChannelPrivate *c = channel->priv; + + if (c->mouse_mode != current) { + c->mouse_mode = current; + g_coroutine_signal_emit(channel, signals[SPICE_MAIN_MOUSE_UPDATE], 0); + g_coroutine_object_notify(G_OBJECT(channel), "mouse-mode"); + } + + if (c->requested_mouse_mode != c->mouse_mode && + c->requested_mouse_mode & supported) { + spice_main_request_mouse_mode(SPICE_MAIN_CHANNEL(channel), c->requested_mouse_mode); + } +} + +/* coroutine context */ +static void main_handle_init(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + SpiceMsgMainInit *init = spice_msg_in_parsed(in); + SpiceSession *session; + SpiceMsgOut *out; + + session = spice_channel_get_session(channel); + spice_session_set_connection_id(session, init->session_id); + + set_mouse_mode(SPICE_MAIN_CHANNEL(channel), init->supported_mouse_modes, + init->current_mouse_mode); + + spice_session_set_mm_time(session, init->multi_media_time); + spice_session_set_caches_hints(session, init->ram_hint, init->display_channels_hint); + + c->agent_tokens = init->agent_tokens; + if (init->agent_connected) + agent_start(SPICE_MAIN_CHANNEL(channel)); + + if (spice_session_migrate_after_main_init(session)) + return; + + out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_ATTACH_CHANNELS); + spice_msg_out_send_internal(out); +} + +/* coroutine context */ +static void main_handle_name(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainName *name = spice_msg_in_parsed(in); + SpiceSession *session = spice_channel_get_session(channel); + + SPICE_DEBUG("server name: %s", name->name); + spice_session_set_name(session, (const gchar *)name->name); +} + +/* coroutine context */ +static void main_handle_uuid(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainUuid *uuid = spice_msg_in_parsed(in); + SpiceSession *session = spice_channel_get_session(channel); + gchar *uuid_str = spice_uuid_to_string(uuid->uuid); + + SPICE_DEBUG("server uuid: %s", uuid_str); + spice_session_set_uuid(session, uuid->uuid); + + g_free(uuid_str); +} + +/* coroutine context */ +static void main_handle_mm_time(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceSession *session; + SpiceMsgMainMultiMediaTime *msg = spice_msg_in_parsed(in); + + session = spice_channel_get_session(channel); + spice_session_set_mm_time(session, msg->time); +} + +typedef struct channel_new { + SpiceSession *session; + int type; + int id; +} channel_new_t; + +/* main context */ +static gboolean _channel_new(channel_new_t *c) +{ + g_return_val_if_fail(c != NULL, FALSE); + + spice_channel_new(c->session, c->type, c->id); + + g_object_unref(c->session); + g_free(c); + + return FALSE; +} + +/* coroutine context */ +static void main_handle_channels_list(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgChannels *msg = spice_msg_in_parsed(in); + SpiceSession *session; + int i; + + session = spice_channel_get_session(channel); + + /* guarantee that uuid is notified before setting up the channels, even if + * the server is older and doesn't actually send the uuid */ + g_coroutine_object_notify(G_OBJECT(session), "uuid"); + + for (i = 0; i < msg->num_of_channels; i++) { + channel_new_t *c; + + c = g_new(channel_new_t, 1); + c->session = g_object_ref(session); + c->type = msg->channels[i].type; + c->id = msg->channels[i].id; + /* no need to explicitely switch to main context, since + synchronous call is not needed. */ + /* no need to track idle, session is refed */ + g_idle_add((GSourceFunc)_channel_new, c); + } +} + +/* coroutine context */ +static void main_handle_mouse_mode(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainMouseMode *msg = spice_msg_in_parsed(in); + set_mouse_mode(SPICE_MAIN_CHANNEL(channel), msg->supported_modes, msg->current_mode); +} + +/* coroutine context */ +static void main_handle_agent_connected(SpiceChannel *channel, SpiceMsgIn *in) +{ + agent_start(SPICE_MAIN_CHANNEL(channel)); +} + +/* coroutine context */ +static void main_handle_agent_connected_tokens(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + SpiceMsgMainAgentConnectedTokens *msg = spice_msg_in_parsed(in); + + c->agent_tokens = msg->num_tokens; + agent_start(SPICE_MAIN_CHANNEL(channel)); +} + +/* coroutine context */ +static void main_handle_agent_disconnected(SpiceChannel *channel, SpiceMsgIn *in) +{ + agent_stopped(SPICE_MAIN_CHANNEL(channel)); +} + +/* main context */ +static void file_xfer_close_cb(GObject *object, + GAsyncResult *close_res, + gpointer user_data) +{ + GTask *task; + SpiceFileTransferTask *self; + GError *error = NULL; + + self = user_data; + + if (object) { + GInputStream *stream = G_INPUT_STREAM(object); + g_input_stream_close_finish(stream, close_res, &error); + if (error) { + /* This error dont need to report to user, just print a log */ + SPICE_DEBUG("close file error: %s", error->message); + g_clear_error(&error); + } + } + + /* Notify to user that files have been transferred or something error + happened. */ + task = g_task_new(self->channel, + self->cancellable, + self->callback, + self->user_data); + + if (self->error) { + g_task_return_error(task, self->error); + } else { + g_task_return_boolean(task, TRUE); + if (spice_util_get_debug()) { + gint64 now = g_get_monotonic_time(); + gchar *basename = g_file_get_basename(self->file); + double seconds = (double) (now - self->start_time) / G_TIME_SPAN_SECOND; + gchar *file_size_str = g_format_size(self->file_size); + gchar *transfer_speed_str = g_format_size(self->file_size / seconds); + + g_warn_if_fail(self->read_bytes == self->file_size); + SPICE_DEBUG("transferred file %s of %s size in %.1f seconds (%s/s)", + basename, file_size_str, seconds, transfer_speed_str); + + g_free(basename); + g_free(file_size_str); + g_free(transfer_speed_str); + } + } + g_object_unref(task); + + g_object_unref(self); +} + +static void file_xfer_data_flushed_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceFileTransferTask *self = user_data; + SpiceMainChannel *channel = (SpiceMainChannel *)source_object; + GError *error = NULL; + + self->pending = FALSE; + file_xfer_flush_finish(channel, res, &error); + if (error || self->error) { + spice_file_transfer_task_completed(self, error); + return; + } + + if (spice_util_get_debug()) { + const GTimeSpan interval = 20 * G_TIME_SPAN_SECOND; + gint64 now = g_get_monotonic_time(); + + if (interval < now - self->last_update) { + gchar *basename = g_file_get_basename(self->file); + self->last_update = now; + SPICE_DEBUG("transferred %.2f%% of the file %s", + 100.0 * self->read_bytes / self->file_size, basename); + g_free(basename); + } + } + + if (self->progress_callback) { + goffset read = 0; + goffset total = 0; + SpiceMainChannel *main_channel = self->channel; + GHashTableIter iter; + gpointer key, value; + + /* since the progress_callback does not have a parameter to indicate + * which file the progress is associated with, report progress on all + * current transfers */ + g_hash_table_iter_init(&iter, main_channel->priv->file_xfer_tasks); + while (g_hash_table_iter_next(&iter, &key, &value)) { + SpiceFileTransferTask *t = (SpiceFileTransferTask *)value; + read += t->read_bytes; + total += t->file_size; + } + + self->progress_callback(read, total, self->progress_callback_data); + } + + /* Read more data */ + file_xfer_continue_read(self); +} + +static void file_xfer_queue(SpiceFileTransferTask *self, int data_size) +{ + VDAgentFileXferDataMessage msg; + SpiceMainChannel *channel = SPICE_MAIN_CHANNEL(self->channel); + + msg.id = self->id; + msg.size = data_size; + agent_msg_queue_many(channel, VD_AGENT_FILE_XFER_DATA, + &msg, sizeof(msg), + self->buffer, data_size, NULL); + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); +} + +/* main context */ +static void file_xfer_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceFileTransferTask *self = user_data; + SpiceMainChannel *channel = self->channel; + gssize count; + GError *error = NULL; + + self->pending = FALSE; + count = g_input_stream_read_finish(G_INPUT_STREAM(self->file_stream), + res, &error); + /* Check for pending earlier errors */ + if (self->error) { + spice_file_transfer_task_completed(self, error); + return; + } + + if (count > 0 || self->file_size == 0) { + self->read_bytes += count; + g_object_notify(G_OBJECT(self), "progress"); + file_xfer_queue(self, count); + if (count == 0) + return; + file_xfer_flush_async(channel, self->cancellable, + file_xfer_data_flushed_cb, self); + self->pending = TRUE; + } else if (error) { + spice_channel_wakeup(SPICE_CHANNEL(self->channel), FALSE); + spice_file_transfer_task_completed(self, error); + } + /* else EOF, do nothing (wait for VD_AGENT_FILE_XFER_STATUS from agent) */ +} + +/* coroutine context */ +static void file_xfer_continue_read(SpiceFileTransferTask *self) +{ + g_input_stream_read_async(G_INPUT_STREAM(self->file_stream), + self->buffer, + FILE_XFER_CHUNK_SIZE, + G_PRIORITY_DEFAULT, + self->cancellable, + file_xfer_read_cb, + self); + self->pending = TRUE; +} + +/* coroutine context */ +static void spice_file_transfer_task_handle_status(SpiceFileTransferTask *task, + VDAgentFileXferStatusMessage *msg) +{ + GError *error = NULL; + g_return_if_fail(task != NULL); + + SPICE_DEBUG("task %u received response %u", msg->id, msg->result); + + switch (msg->result) { + case VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA: + if (task->pending) { + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "transfer received CAN_SEND_DATA in pending state"); + break; + } + file_xfer_continue_read(task); + return; + case VD_AGENT_FILE_XFER_STATUS_CANCELLED: + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "transfer is cancelled by spice agent"); + break; + case VD_AGENT_FILE_XFER_STATUS_ERROR: + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "some errors occurred in the spice agent"); + break; + case VD_AGENT_FILE_XFER_STATUS_SUCCESS: + if (task->pending) + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "transfer received success in pending state"); + break; + default: + g_warn_if_reached(); + error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "unhandled status type: %u", msg->result); + break; + } + + spice_file_transfer_task_completed(task, error); +} + +/* any context: the message is not flushed immediately, + you can wakeup() the channel coroutine or send_msg_queue() */ +static void agent_max_clipboard(SpiceMainChannel *self) +{ + VDAgentMaxClipboard msg = { .max = spice_main_get_max_clipboard(self) }; + + if (!test_agent_cap(self, VD_AGENT_CAP_MAX_CLIPBOARD)) + return; + + agent_msg_queue(self, VD_AGENT_MAX_CLIPBOARD, sizeof(VDAgentMaxClipboard), &msg); +} + +static void spice_main_set_max_clipboard(SpiceMainChannel *self, gint max) +{ + SpiceMainChannelPrivate *c; + + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(self)); + g_return_if_fail(max >= -1); + + c = self->priv; + if (max == spice_main_get_max_clipboard(self)) + return; + + c->max_clipboard = max; + agent_max_clipboard(self); + spice_channel_wakeup(SPICE_CHANNEL(self), FALSE); +} + +/* coroutine context */ +static void main_agent_handle_msg(SpiceChannel *channel, + VDAgentMessage *msg, gpointer payload) +{ + SpiceMainChannel *self = SPICE_MAIN_CHANNEL(channel); + SpiceMainChannelPrivate *c = self->priv; + guint8 selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + + g_return_if_fail(msg->protocol == VD_AGENT_PROTOCOL); + + switch (msg->type) { + case VD_AGENT_CLIPBOARD_RELEASE: + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD_GRAB: + case VD_AGENT_CLIPBOARD: + if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + selection = *((guint8*)payload); + payload = ((guint8*)payload) + 4; + msg->size -= 4; + } + break; + default: + break; + } + + switch (msg->type) { + case VD_AGENT_ANNOUNCE_CAPABILITIES: + { + VDAgentAnnounceCapabilities *caps = payload; + int i, size; + + size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(msg->size); + if (size > VD_AGENT_CAPS_SIZE) + size = VD_AGENT_CAPS_SIZE; + memset(c->agent_caps, 0, sizeof(c->agent_caps)); + for (i = 0; i < size * 32; i++) { + if (!VD_AGENT_HAS_CAPABILITY(caps->caps, size, i)) + continue; + SPICE_DEBUG("%s: cap: %d (%s)", __FUNCTION__, + i, NAME(agent_caps, i)); + VD_AGENT_SET_CAPABILITY(c->agent_caps, i); + } + c->agent_caps_received = true; + g_coroutine_signal_emit(self, signals[SPICE_MAIN_AGENT_UPDATE], 0); + update_display_timer(SPICE_MAIN_CHANNEL(channel), 0); + + if (caps->request) + agent_announce_caps(self); + + if (test_agent_cap(self, VD_AGENT_CAP_DISPLAY_CONFIG) && + !c->agent_display_config_sent) { + agent_display_config(self); + c->agent_display_config_sent = true; + } + + agent_sync_audio_playback(self); + agent_sync_audio_record(self); + + agent_max_clipboard(self); + + agent_send_msg_queue(self); + + break; + } + case VD_AGENT_CLIPBOARD: + { + VDAgentClipboard *cb = payload; + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION], 0, selection, + cb->type, cb->data, msg->size - sizeof(VDAgentClipboard)); + + if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD], 0, + cb->type, cb->data, msg->size - sizeof(VDAgentClipboard)); + break; + } + case VD_AGENT_CLIPBOARD_GRAB: + { + gboolean ret; + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB], 0, selection, + (guint8*)payload, msg->size / sizeof(uint32_t), &ret); + if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_GRAB], 0, + payload, msg->size / sizeof(uint32_t), &ret); + break; + } + case VD_AGENT_CLIPBOARD_REQUEST: + { + gboolean ret; + VDAgentClipboardRequest *req = payload; + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST], 0, selection, + req->type, &ret); + + if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_REQUEST], 0, + req->type, &ret); + break; + } + case VD_AGENT_CLIPBOARD_RELEASE: + { + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE], 0, selection); + + if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_RELEASE], 0); + break; + } + case VD_AGENT_REPLY: + { + VDAgentReply *reply = payload; + SPICE_DEBUG("%s: reply: type %u, %s", __FUNCTION__, reply->type, + reply->error == VD_AGENT_SUCCESS ? "success" : "error"); + break; + } + case VD_AGENT_FILE_XFER_STATUS: + { + SpiceFileTransferTask *task; + VDAgentFileXferStatusMessage *msg = payload; + + task = g_hash_table_lookup(c->file_xfer_tasks, GUINT_TO_POINTER(msg->id)); + if (task != NULL) { + spice_file_transfer_task_handle_status(task, msg); + } else { + SPICE_DEBUG("cannot find task %u", msg->id); + } + break; + } + default: + g_warning("unhandled agent message type: %u (%s), size %u", + msg->type, NAME(agent_msg_types, msg->type), msg->size); + } +} + +/* coroutine context */ +static void main_handle_agent_data_msg(SpiceChannel* channel, int* msg_size, guchar** msg_pos) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + int n; + + if (c->agent_msg_pos < sizeof(VDAgentMessage)) { + n = MIN(sizeof(VDAgentMessage) - c->agent_msg_pos, *msg_size); + memcpy((uint8_t*)&c->agent_msg + c->agent_msg_pos, *msg_pos, n); + c->agent_msg_pos += n; + *msg_size -= n; + *msg_pos += n; + if (c->agent_msg_pos == sizeof(VDAgentMessage)) { + SPICE_DEBUG("agent msg start: msg_size=%u, protocol=%u, type=%u", + c->agent_msg.size, c->agent_msg.protocol, c->agent_msg.type); + g_return_if_fail(c->agent_msg_data == NULL); + c->agent_msg_data = g_malloc0(c->agent_msg.size); + } + } + + if (c->agent_msg_pos >= sizeof(VDAgentMessage)) { + n = MIN(sizeof(VDAgentMessage) + c->agent_msg.size - c->agent_msg_pos, *msg_size); + memcpy(c->agent_msg_data + c->agent_msg_pos - sizeof(VDAgentMessage), *msg_pos, n); + c->agent_msg_pos += n; + *msg_size -= n; + *msg_pos += n; + } + + if (c->agent_msg_pos == sizeof(VDAgentMessage) + c->agent_msg.size) { + main_agent_handle_msg(channel, &c->agent_msg, c->agent_msg_data); + g_free(c->agent_msg_data); + c->agent_msg_data = NULL; + c->agent_msg_pos = 0; + } +} + +/* coroutine context */ +static void main_handle_agent_data(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + guint8 *data; + int len; + + g_warn_if_fail(c->agent_connected); + + /* shortcut to avoid extra message allocation & copy if possible */ + if (c->agent_msg_pos == 0) { + VDAgentMessage *msg; + guint msg_size; + + msg = spice_msg_in_raw(in, &len); + msg_size = msg->size; + + if (msg_size + sizeof(VDAgentMessage) == len) { + main_agent_handle_msg(channel, msg, msg->data); + return; + } + } + + data = spice_msg_in_raw(in, &len); + while (len > 0) { + main_handle_agent_data_msg(channel, &len, &data); + } +} + +/* coroutine context */ +static void main_handle_agent_token(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainAgentTokens *tokens = spice_msg_in_parsed(in); + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + c->agent_tokens += tokens->num_tokens; + + agent_send_msg_queue(SPICE_MAIN_CHANNEL(channel)); +} + +/* main context */ +static void migrate_channel_new_cb(SpiceSession *s, SpiceChannel *channel, gpointer data) +{ + g_signal_connect(channel, "channel-event", + G_CALLBACK(migrate_channel_event_cb), data); +} + +static SpiceChannel* migrate_channel_connect(spice_migrate *mig, int type, int id) +{ + SPICE_DEBUG("migrate_channel_connect %d:%d", type, id); + + SpiceChannel *newc = spice_channel_new(mig->session, type, id); + spice_channel_connect(newc); + mig->nchannels++; + + return newc; +} + +/* coroutine context */ +static void spice_main_channel_send_migration_handshake(SpiceChannel *channel) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + if (!spice_channel_test_capability(channel, SPICE_MAIN_CAP_SEAMLESS_MIGRATE)) { + c->migrate_data->do_seamless = false; + g_idle_add(main_migrate_handshake_done, c->migrate_data); + } else { + SpiceMsgcMainMigrateDstDoSeamless msg_data; + SpiceMsgOut *msg_out; + + msg_data.src_version = c->migrate_data->src_mig_version; + + msg_out = spice_msg_out_new(channel, SPICE_MSGC_MAIN_MIGRATE_DST_DO_SEAMLESS); + msg_out->marshallers->msgc_main_migrate_dst_do_seamless(msg_out->marshaller, &msg_data); + spice_msg_out_send_internal(msg_out); + } +} + +/* main context */ +static void migrate_channel_event_cb(SpiceChannel *channel, SpiceChannelEvent event, + gpointer data) +{ + spice_migrate *mig = data; + SpiceChannelPrivate *c = SPICE_CHANNEL(channel)->priv; + + g_return_if_fail(mig->nchannels > 0); + g_signal_handlers_disconnect_by_func(channel, migrate_channel_event_cb, data); + + switch (event) { + case SPICE_CHANNEL_OPENED: + if (c->channel_type == SPICE_CHANNEL_MAIN) { + SpiceSession *session = spice_channel_get_session(mig->src_channel); + if (mig->do_seamless) { + SpiceMainChannelPrivate *main_priv = SPICE_MAIN_CHANNEL(channel)->priv; + + c->state = SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE; + mig->dst_channel = channel; + main_priv->migrate_data = mig; + } else { + c->state = SPICE_CHANNEL_STATE_MIGRATING; + mig->nchannels--; + } + /* now connect the rest of the channels */ + GList *channels, *l; + l = channels = spice_session_get_channels(session); + while (l != NULL) { + SpiceChannelPrivate *curc = SPICE_CHANNEL(l->data)->priv; + l = l->next; + if (curc->channel_type == SPICE_CHANNEL_MAIN) + continue; + migrate_channel_connect(mig, curc->channel_type, curc->channel_id); + } + g_list_free(channels); + } else { + c->state = SPICE_CHANNEL_STATE_MIGRATING; + mig->nchannels--; + } + + SPICE_DEBUG("migration: channel opened chan:%p, left %u", channel, mig->nchannels); + if (mig->nchannels == 0) + coroutine_yieldto(mig->from, NULL); + break; + default: + CHANNEL_DEBUG(channel, "error or unhandled channel event during migration: %u", event); + /* go back to main channel to report error */ + coroutine_yieldto(mig->from, NULL); + } +} + +/* main context */ +static gboolean main_migrate_handshake_done(gpointer data) +{ + spice_migrate *mig = data; + SpiceChannelPrivate *c = SPICE_CHANNEL(mig->dst_channel)->priv; + + g_return_val_if_fail(c->channel_type == SPICE_CHANNEL_MAIN, FALSE); + g_return_val_if_fail(c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE, FALSE); + + c->state = SPICE_CHANNEL_STATE_MIGRATING; + mig->nchannels--; + if (mig->nchannels == 0) + coroutine_yieldto(mig->from, NULL); + return FALSE; +} + +#ifdef __GNUC__ +typedef struct __attribute__ ((__packed__)) OldRedMigrationBegin { +#else +typedef struct __declspec(align(1)) OldRedMigrationBegin { +#endif + uint16_t port; + uint16_t sport; + char host[0]; +} OldRedMigrationBegin; + +/* main context */ +static gboolean migrate_connect(gpointer data) +{ + spice_migrate *mig = data; + SpiceChannelPrivate *c; + int port, sport; + const char *host; + + g_return_val_if_fail(mig != NULL, FALSE); + g_return_val_if_fail(mig->info != NULL, FALSE); + g_return_val_if_fail(mig->nchannels == 0, FALSE); + c = SPICE_CHANNEL(mig->src_channel)->priv; + g_return_val_if_fail(c != NULL, FALSE); + g_return_val_if_fail(mig->session != NULL, FALSE); + + spice_session_set_migration_state(mig->session, SPICE_SESSION_MIGRATION_CONNECTING); + + if ((c->peer_hdr.major_version == 1) && + (c->peer_hdr.minor_version < 1)) { + OldRedMigrationBegin *info = (OldRedMigrationBegin *)mig->info; + SPICE_DEBUG("migrate_begin old %s %d %d", + info->host, info->port, info->sport); + port = info->port; + sport = info->sport; + host = info->host; + } else { + SpiceMigrationDstInfo *info = mig->info; + SPICE_DEBUG("migrate_begin %u %s %d %d", + info->host_size, info->host_data, info->port, info->sport); + port = info->port; + sport = info->sport; + host = (char*)info->host_data; + + if ((c->peer_hdr.major_version == 1) || + (c->peer_hdr.major_version == 2 && c->peer_hdr.minor_version < 1)) { + GByteArray *pubkey = g_byte_array_new(); + + g_byte_array_append(pubkey, info->pub_key_data, info->pub_key_size); + g_object_set(mig->session, + "pubkey", pubkey, + "verify", SPICE_SESSION_VERIFY_PUBKEY, + NULL); + g_byte_array_unref(pubkey); + } else if (info->cert_subject_size == 0 || + strlen((const char*)info->cert_subject_data) == 0) { + /* only verify hostname if no cert subject */ + g_object_set(mig->session, "verify", SPICE_SESSION_VERIFY_HOSTNAME, NULL); + } else { + gchar *subject = g_alloca(info->cert_subject_size + 1); + strncpy(subject, (const char*)info->cert_subject_data, info->cert_subject_size); + subject[info->cert_subject_size] = '\0'; + + // session data are already copied + g_object_set(mig->session, + "cert-subject", subject, + "verify", SPICE_SESSION_VERIFY_SUBJECT, + NULL); + } + } + + if (g_getenv("SPICE_MIG_HOST")) + host = g_getenv("SPICE_MIG_HOST"); + + g_object_set(mig->session, "host", host, NULL); + spice_session_set_port(mig->session, port, FALSE); + spice_session_set_port(mig->session, sport, TRUE); + g_signal_connect(mig->session, "channel-new", + G_CALLBACK(migrate_channel_new_cb), mig); + + g_signal_emit(mig->src_channel, signals[SPICE_MIGRATION_STARTED], 0, + mig->session); + + /* the migration process is in 2 steps, first the main channel and + then the rest of the channels */ + migrate_channel_connect(mig, SPICE_CHANNEL_MAIN, 0); + + return FALSE; +} + +/* coroutine context */ +static void main_migrate_connect(SpiceChannel *channel, + SpiceMigrationDstInfo *dst_info, bool do_seamless, + uint32_t src_mig_version) +{ + SpiceMainChannelPrivate *main_priv = SPICE_MAIN_CHANNEL(channel)->priv; + int reply_type = SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR; + spice_migrate mig = { 0, }; + SpiceMsgOut *out; + SpiceSession *session; + + mig.src_channel = channel; + mig.info = dst_info; + mig.from = coroutine_self(); + mig.do_seamless = do_seamless; + mig.src_mig_version = src_mig_version; + + CHANNEL_DEBUG(channel, "migrate connect"); + session = spice_channel_get_session(channel); + mig.session = spice_session_new_from_session(session); + if (mig.session == NULL) + goto end; + if (!spice_session_set_migration_session(session, mig.session)) + goto end; + + main_priv->migrate_data = &mig; + + /* no need to track idle, call is sync for this coroutine */ + g_idle_add(migrate_connect, &mig); + + /* switch to main loop and wait for connections */ + coroutine_yield(NULL); + + if (mig.nchannels != 0) { + CHANNEL_DEBUG(channel, "migrate failed: some channels failed to connect"); + spice_session_abort_migration(session); + } else { + if (mig.do_seamless) { + SPICE_DEBUG("migration (seamless): connections all ok"); + reply_type = SPICE_MSGC_MAIN_MIGRATE_CONNECTED_SEAMLESS; + } else { + SPICE_DEBUG("migration (semi-seamless): connections all ok"); + reply_type = SPICE_MSGC_MAIN_MIGRATE_CONNECTED; + } + spice_session_start_migrating(spice_channel_get_session(channel), + mig.do_seamless); + } + +end: + CHANNEL_DEBUG(channel, "migrate connect reply %d", reply_type); + out = spice_msg_out_new(SPICE_CHANNEL(channel), reply_type); + spice_msg_out_send(out); +} + +/* coroutine context */ +static void main_handle_migrate_begin(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainMigrationBegin *msg = spice_msg_in_parsed(in); + + main_migrate_connect(channel, &msg->dst_info, false, 0); +} + +/* coroutine context */ +static void main_handle_migrate_begin_seamless(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainMigrateBeginSeamless *msg = spice_msg_in_parsed(in); + + main_migrate_connect(channel, &msg->dst_info, true, msg->src_mig_version); +} + +static void main_handle_migrate_dst_seamless_ack(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = SPICE_CHANNEL(channel)->priv; + SpiceMainChannelPrivate *main_priv = SPICE_MAIN_CHANNEL(channel)->priv; + + g_return_if_fail(c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE); + main_priv->migrate_data->do_seamless = true; + g_idle_add(main_migrate_handshake_done, main_priv->migrate_data); +} + +static void main_handle_migrate_dst_seamless_nack(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = SPICE_CHANNEL(channel)->priv; + SpiceMainChannelPrivate *main_priv = SPICE_MAIN_CHANNEL(channel)->priv; + + g_return_if_fail(c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE); + main_priv->migrate_data->do_seamless = false; + g_idle_add(main_migrate_handshake_done, main_priv->migrate_data); +} + +/* main context */ +static gboolean migrate_delayed(gpointer data) +{ + SpiceChannel *channel = data; + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + g_warn_if_fail(c->migrate_delayed_id != 0); + c->migrate_delayed_id = 0; + + spice_session_migrate_end(channel->priv->session); + + return FALSE; +} + +/* coroutine context */ +static void main_handle_migrate_end(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + SPICE_DEBUG("migrate end"); + + g_return_if_fail(c->migrate_delayed_id == 0); + g_return_if_fail(spice_channel_test_capability(channel, SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE)); + + c->migrate_delayed_id = g_idle_add(migrate_delayed, channel); +} + +/* main context */ +static gboolean switch_host_delayed(gpointer data) +{ + SpiceChannel *channel = data; + SpiceSession *session; + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + g_warn_if_fail(c->switch_host_delayed_id != 0); + c->switch_host_delayed_id = 0; + + session = spice_channel_get_session(channel); + + spice_channel_disconnect(channel, SPICE_CHANNEL_SWITCHING); + spice_session_switching_disconnect(session); + + return FALSE; +} + +/* coroutine context */ +static void main_handle_migrate_switch_host(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceMsgMainMigrationSwitchHost *mig = spice_msg_in_parsed(in); + SpiceSession *session; + char *host = (char *)mig->host_data; + char *subject = NULL; + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + g_return_if_fail(host[mig->host_size - 1] == '\0'); + + if (mig->cert_subject_size) { + subject = (char *)mig->cert_subject_data; + g_return_if_fail(subject[mig->cert_subject_size - 1] == '\0'); + } + + SPICE_DEBUG("migrate_switch %s %d %d %s", + host, mig->port, mig->sport, subject); + + if (c->switch_host_delayed_id != 0) { + g_warning("Switching host already in progress, aborting it"); + g_warn_if_fail(g_source_remove(c->switch_host_delayed_id)); + c->switch_host_delayed_id = 0; + } + + session = spice_channel_get_session(channel); + spice_session_set_migration_state(session, SPICE_SESSION_MIGRATION_SWITCHING); + g_object_set(session, + "host", host, + "cert-subject", subject, + NULL); + spice_session_set_port(session, mig->port, FALSE); + spice_session_set_port(session, mig->sport, TRUE); + + c->switch_host_delayed_id = g_idle_add(switch_host_delayed, channel); +} + +/* coroutine context */ +static void main_handle_migrate_cancel(SpiceChannel *channel, + SpiceMsgIn *in G_GNUC_UNUSED) +{ + SpiceSession *session; + + SPICE_DEBUG("migrate_cancel"); + session = spice_channel_get_session(channel); + spice_session_abort_migration(session); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_MAIN_INIT ] = main_handle_init, + [ SPICE_MSG_MAIN_NAME ] = main_handle_name, + [ SPICE_MSG_MAIN_UUID ] = main_handle_uuid, + [ SPICE_MSG_MAIN_CHANNELS_LIST ] = main_handle_channels_list, + [ SPICE_MSG_MAIN_MOUSE_MODE ] = main_handle_mouse_mode, + [ SPICE_MSG_MAIN_MULTI_MEDIA_TIME ] = main_handle_mm_time, + + [ SPICE_MSG_MAIN_AGENT_CONNECTED ] = main_handle_agent_connected, + [ SPICE_MSG_MAIN_AGENT_DISCONNECTED ] = main_handle_agent_disconnected, + [ SPICE_MSG_MAIN_AGENT_DATA ] = main_handle_agent_data, + [ SPICE_MSG_MAIN_AGENT_TOKEN ] = main_handle_agent_token, + + [ SPICE_MSG_MAIN_MIGRATE_BEGIN ] = main_handle_migrate_begin, + [ SPICE_MSG_MAIN_MIGRATE_END ] = main_handle_migrate_end, + [ SPICE_MSG_MAIN_MIGRATE_CANCEL ] = main_handle_migrate_cancel, + [ SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST ] = main_handle_migrate_switch_host, + [ SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS ] = main_handle_agent_connected_tokens, + [ SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS ] = main_handle_migrate_begin_seamless, + [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK] = main_handle_migrate_dst_seamless_ack, + [ SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK] = main_handle_migrate_dst_seamless_nack, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +/* coroutine context */ +static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg) +{ + int type = spice_msg_in_type(msg); + SpiceChannelClass *parent_class; + SpiceChannelPrivate *c = SPICE_CHANNEL(channel)->priv; + + parent_class = SPICE_CHANNEL_CLASS(spice_main_channel_parent_class); + + if (c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE) { + if (type != SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK && + type != SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK) { + g_critical("unexpected msg (%d)." + "Only MIGRATE_DST_SEAMLESS_ACK/NACK are allowed", type); + return; + } + } + + parent_class->handle_msg(channel, msg); +} + +/** + * spice_main_agent_test_capability: + * @channel: a #SpiceMainChannel + * @cap: an agent capability identifier + * + * Test capability of a remote agent. + * + * Returns: %TRUE if @cap (channel kind capability) is available. + **/ +gboolean spice_main_agent_test_capability(SpiceMainChannel *channel, guint32 cap) +{ + g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE); + + return test_agent_cap(channel, cap); +} + +/** + * spice_main_update_display: + * @channel: a #SpiceMainChannel + * @id: display ID + * @x: x position + * @y: y position + * @width: display width + * @height: display height + * @update: if %TRUE, update guest resolution after 1sec. + * + * Update the display @id resolution. + * + * If @update is %TRUE, the remote configuration will be updated too + * after 1 second without further changes. You can send when you want + * without delay the new configuration to the remote with + * spice_main_send_monitor_config() + **/ +void spice_main_update_display(SpiceMainChannel *channel, int id, + int x, int y, int width, int height, + gboolean update) +{ + SpiceMainChannelPrivate *c; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + g_return_if_fail(x >= 0); + g_return_if_fail(y >= 0); + g_return_if_fail(width >= 0); + g_return_if_fail(height >= 0); + + c = SPICE_MAIN_CHANNEL(channel)->priv; + + g_return_if_fail(id < SPICE_N_ELEMENTS(c->display)); + + SpiceDisplayConfig display = { + .x = x, .y = y, .width = width, .height = height, + .display_state = c->display[id].display_state + }; + + if (memcmp(&display, &c->display[id], sizeof(SpiceDisplayConfig)) == 0) + return; + + c->display[id] = display; + + if (update) + update_display_timer(channel, 1); +} + +/** + * spice_main_set_display: + * @channel: a #SpiceMainChannel + * @id: display ID + * @x: x position + * @y: y position + * @width: display width + * @height: display height + * + * Notify the guest of screen resolution change. The notification is + * sent 1 second later, if no further changes happen. + **/ +void spice_main_set_display(SpiceMainChannel *channel, int id, + int x, int y, int width, int height) +{ + spice_main_update_display(channel, id, x, y, width, height, TRUE); +} + +/** + * spice_main_clipboard_grab: + * @channel: a #SpiceMainChannel + * @types: an array of #VD_AGENT_CLIPBOARD types available in the clipboard + * @ntypes: the number of @types + * + * Grab the guest clipboard, with #VD_AGENT_CLIPBOARD @types. + * + * Deprecated: 0.6: use spice_main_clipboard_selection_grab() instead. + **/ +void spice_main_clipboard_grab(SpiceMainChannel *channel, guint32 *types, int ntypes) +{ + spice_main_clipboard_selection_grab(channel, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, types, ntypes); +} + +/** + * spice_main_clipboard_selection_grab: + * @channel: a #SpiceMainChannel + * @selection: one of the clipboard #VD_AGENT_CLIPBOARD_SELECTION_* + * @types: an array of #VD_AGENT_CLIPBOARD types available in the clipboard + * @ntypes: the number of @types + * + * Grab the guest clipboard, with #VD_AGENT_CLIPBOARD @types. + * + * Since: 0.6 + **/ +void spice_main_clipboard_selection_grab(SpiceMainChannel *channel, guint selection, + guint32 *types, int ntypes) +{ + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + + agent_clipboard_grab(channel, selection, types, ntypes); + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); +} + +/** + * spice_main_clipboard_release: + * @channel: a #SpiceMainChannel + * + * Release the clipboard (for example, when the client loses the + * clipboard grab): Inform the guest no clipboard data is available. + * + * Deprecated: 0.6: use spice_main_clipboard_selection_release() instead. + **/ +void spice_main_clipboard_release(SpiceMainChannel *channel) +{ + spice_main_clipboard_selection_release(channel, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD); +} + +/** + * spice_main_clipboard_selection_release: + * @channel: a #SpiceMainChannel + * @selection: one of the clipboard #VD_AGENT_CLIPBOARD_SELECTION_* + * + * Release the clipboard (for example, when the client loses the + * clipboard grab): Inform the guest no clipboard data is available. + * + * Since: 0.6 + **/ +void spice_main_clipboard_selection_release(SpiceMainChannel *channel, guint selection) +{ + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + + SpiceMainChannelPrivate *c = channel->priv; + + if (!c->agent_connected) + return; + + agent_clipboard_release(channel, selection); + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); +} + +/** + * spice_main_clipboard_notify: + * @channel: a #SpiceMainChannel + * @type: a #VD_AGENT_CLIPBOARD type + * @data: clipboard data + * @size: data length in bytes + * + * Send the clipboard data to the guest. + * + * Deprecated: 0.6: use spice_main_clipboard_selection_notify() instead. + **/ +void spice_main_clipboard_notify(SpiceMainChannel *channel, + guint32 type, const guchar *data, size_t size) +{ + spice_main_clipboard_selection_notify(channel, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, + type, data, size); +} + +/** + * spice_main_clipboard_selection_notify: + * @channel: a #SpiceMainChannel + * @selection: one of the clipboard #VD_AGENT_CLIPBOARD_SELECTION_* + * @type: a #VD_AGENT_CLIPBOARD type + * @data: clipboard data + * @size: data length in bytes + * + * Send the clipboard data to the guest. + * + * Since: 0.6 + **/ +void spice_main_clipboard_selection_notify(SpiceMainChannel *channel, guint selection, + guint32 type, const guchar *data, size_t size) +{ + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + + agent_clipboard_notify(channel, selection, type, data, size); + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); +} + +/** + * spice_main_clipboard_request: + * @channel: a #SpiceMainChannel + * @type: a #VD_AGENT_CLIPBOARD type + * + * Request clipboard data of @type from the guest. The reply is sent + * through the #SpiceMainChannel::main-clipboard signal. + * + * Deprecated: 0.6: use spice_main_clipboard_selection_request() instead. + **/ +void spice_main_clipboard_request(SpiceMainChannel *channel, guint32 type) +{ + spice_main_clipboard_selection_request(channel, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, type); +} + +/** + * spice_main_clipboard_selection_request: + * @channel: a #SpiceMainChannel + * @selection: one of the clipboard #VD_AGENT_CLIPBOARD_SELECTION_* + * @type: a #VD_AGENT_CLIPBOARD type + * + * Request clipboard data of @type from the guest. The reply is sent + * through the #SpiceMainChannel::main-clipboard-selection signal. + * + * Since: 0.6 + **/ +void spice_main_clipboard_selection_request(SpiceMainChannel *channel, guint selection, guint32 type) +{ + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + + agent_clipboard_request(channel, selection, type); + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE); +} + +/** + * spice_main_update_display_enabled: + * @channel: a #SpiceMainChannel + * @id: display ID (if -1: set all displays) + * @enabled: wether display @id is enabled + * @update: if %TRUE, update guest display state after 1sec. + * + * When sending monitor configuration to agent guest, if @enabled is %FALSE, + * don't set display @id, which the agent translates to disabling the display + * id. If @enabled is %TRUE, the monitor will be included in the next monitor + * update. Note: this will take effect next time the monitor configuration is + * sent. + * + * If @update is %FALSE, no server update will be triggered by this call, but + * the value will be saved and used in the next configuration update. + * + * Since: 0.30 + **/ +void spice_main_update_display_enabled(SpiceMainChannel *channel, int id, gboolean enabled, gboolean update) +{ + SpiceDisplayState display_state = enabled ? DISPLAY_ENABLED : DISPLAY_DISABLED; + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + g_return_if_fail(id >= -1); + + SpiceMainChannelPrivate *c = channel->priv; + + if (id == -1) { + gint i; + for (i = 0; i < G_N_ELEMENTS(c->display); i++) { + c->display[i].display_state = display_state; + } + } else { + g_return_if_fail(id < G_N_ELEMENTS(c->display)); + if (c->display[id].display_state == display_state) + return; + c->display[id].display_state = display_state; + } + + if (update) + update_display_timer(channel, 1); +} + +/** + * spice_main_set_display_enabled: + * @channel: a #SpiceMainChannel + * @id: display ID (if -1: set all displays) + * @enabled: wether display @id is enabled + * + * When sending monitor configuration to agent guest, don't set + * display @id, which the agent translates to disabling the display + * id. Note: this will take effect next time the monitor + * configuration is sent. + * + * Since: 0.6 + **/ +void spice_main_set_display_enabled(SpiceMainChannel *channel, int id, gboolean enabled) +{ + spice_main_update_display_enabled(channel, id, enabled, TRUE); +} + +static void spice_file_transfer_task_completed(SpiceFileTransferTask *self, + GError *error) +{ + /* In case of multiple errors we only report the first error */ + if (self->error) + g_clear_error(&error); + if (error) { + gchar *path = g_file_get_path(self->file); + SPICE_DEBUG("File %s xfer failed: %s", + path, error->message); + g_free(path); + self->error = error; + } + + if (self->error) { + VDAgentFileXferStatusMessage msg = { + .id = self->id, + .result = self->error->code == G_IO_ERROR_CANCELLED ? + VD_AGENT_FILE_XFER_STATUS_CANCELLED : VD_AGENT_FILE_XFER_STATUS_ERROR, + }; + agent_msg_queue_many(self->channel, VD_AGENT_FILE_XFER_STATUS, + &msg, sizeof(msg), NULL); + } + + if (self->pending) + return; + + if (!self->file_stream) { + file_xfer_close_cb(NULL, NULL, self); + goto signal; + } + + g_input_stream_close_async(G_INPUT_STREAM(self->file_stream), + G_PRIORITY_DEFAULT, + self->cancellable, + file_xfer_close_cb, + self); + self->pending = TRUE; +signal: + g_signal_emit(self, task_signals[SIGNAL_FINISHED], 0, self->error); +} + + +static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer data) +{ + GFileInfo *info; + GFile *file = G_FILE(obj); + GError *error = NULL; + GKeyFile *keyfile = NULL; + gchar *basename = NULL; + VDAgentFileXferStartMessage msg; + gsize /*msg_size*/ data_len; + gchar *string; + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data); + + self->pending = FALSE; + info = g_file_query_info_finish(file, res, &error); + if (error || self->error) + goto failed; + + self->file_size = + g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_STANDARD_SIZE); + g_object_notify(G_OBJECT(self), "progress"); + keyfile = g_key_file_new(); + + /* File name */ + basename = g_file_get_basename(file); + g_key_file_set_string(keyfile, "vdagent-file-xfer", "name", basename); + g_free(basename); + /* File size */ + g_key_file_set_uint64(keyfile, "vdagent-file-xfer", "size", self->file_size); + + /* Save keyfile content to memory. TODO: more file attributions + need to be sent to guest */ + string = g_key_file_to_data(keyfile, &data_len, &error); + g_key_file_free(keyfile); + if (error) + goto failed; + + /* Create file-xfer start message */ + msg.id = self->id; + agent_msg_queue_many(self->channel, VD_AGENT_FILE_XFER_START, + &msg, sizeof(msg), + string, data_len + 1, NULL); + g_free(string); + spice_channel_wakeup(SPICE_CHANNEL(self->channel), FALSE); + return; + +failed: + spice_file_transfer_task_completed(self, error); +} + +static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer data) +{ + GFile *file = G_FILE(obj); + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data); + GError *error = NULL; + + self->pending = FALSE; + self->file_stream = g_file_read_finish(file, res, &error); + if (error || self->error) { + spice_file_transfer_task_completed(self, error); + return; + } + + g_file_query_info_async(self->file, + G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + self->cancellable, + file_xfer_info_async_cb, + self); + self->pending = TRUE; +} + +static SpiceFileTransferTask *spice_file_transfer_task_new(SpiceMainChannel *channel, + GFile *file, + GCancellable *cancellable); + +static void task_finished(SpiceFileTransferTask *task, + GError *error, + gpointer data) +{ + SpiceMainChannel *channel = SPICE_MAIN_CHANNEL(data); + g_hash_table_remove(channel->priv->file_xfer_tasks, GUINT_TO_POINTER(task->id)); +} + +static void file_xfer_send_start_msg_async(SpiceMainChannel *channel, + GFile **files, + GFileCopyFlags flags, + GCancellable *cancellable, + GFileProgressCallback progress_callback, + gpointer progress_callback_data, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceMainChannelPrivate *c = channel->priv; + SpiceFileTransferTask *task; + gint i; + + for (i = 0; files[i] != NULL && !g_cancellable_is_cancelled(cancellable); i++) { + GCancellable *task_cancellable = cancellable; + /* if a cancellable object was not provided for the overall operation, + * create a separate object for each file so that they can be cancelled + * separately */ + if (!task_cancellable) + task_cancellable = g_cancellable_new(); + + task = spice_file_transfer_task_new(channel, files[i], task_cancellable); + task->flags = flags; + task->progress_callback = progress_callback; + task->progress_callback_data = progress_callback_data; + task->callback = callback; + task->user_data = user_data; + + CHANNEL_DEBUG(channel, "Insert a xfer task:%u to task list", task->id); + g_hash_table_insert(c->file_xfer_tasks, + GUINT_TO_POINTER(task->id), + g_object_ref(task)); + g_signal_connect(task, "finished", G_CALLBACK(task_finished), channel); + g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0, task); + + g_file_read_async(files[i], + G_PRIORITY_DEFAULT, + cancellable, + file_xfer_read_async_cb, + task); + task->pending = TRUE; + + /* if we created a per-task cancellable above, free it */ + if (!cancellable) + g_object_unref(task_cancellable); + } +} + +/** + * spice_main_file_copy_async: + * @channel: a #SpiceMainChannel + * @sources: (array zero-terminated=1): a %NULL-terminated array of #GFile objects to be transferred + * @flags: set of #GFileCopyFlags + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore + * @progress_callback: (allow-none) (scope call): function to callback with + * progress information, or %NULL if progress information is not needed + * @progress_callback_data: (closure): user data to pass to @progress_callback + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: the data to pass to callback function + * + * Copies the file @sources to guest + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * If @progress_callback is not %NULL, then the operation can be monitored by + * setting this to a #GFileProgressCallback function. @progress_callback_data + * will be passed to this function. It is guaranteed that this callback will + * be called after all data has been transferred with the total number of bytes + * copied during the operation. Note that before release 0.31, progress_callback + * was broken since it only provided status for a single file transfer, but did + * not provide a way to determine which file it referred to. In release 0.31, + * this behavior was changed so that progress_callback provides the status of + * all ongoing file transfers. If you need to monitor the status of individual + * files, please connect to the #SpiceMainChannel::new-file-transfer signal. + * + * When the operation is finished, callback will be called. You can then call + * spice_main_file_copy_finish() to get the result of the operation. + * + **/ +void spice_main_file_copy_async(SpiceMainChannel *channel, + GFile **sources, + GFileCopyFlags flags, + GCancellable *cancellable, + GFileProgressCallback progress_callback, + gpointer progress_callback_data, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceMainChannelPrivate *c; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel)); + g_return_if_fail(sources != NULL); + + c = channel->priv; + if (!c->agent_connected) { + g_task_report_new_error(channel, + callback, + user_data, + spice_main_file_copy_async, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "The agent is not connected"); + return; + } + + file_xfer_send_start_msg_async(channel, + sources, + flags, + cancellable, + progress_callback, + progress_callback_data, + callback, + user_data); +} + +/** + * spice_main_file_copy_finish: + * @channel: a #SpiceMainChannel + * @result: a #GAsyncResult. + * @error: a #GError, or %NULL + * + * Finishes copying the file started with + * spice_main_file_copy_async(). + * + * Returns: a %TRUE on success, %FALSE on error. + **/ +gboolean spice_main_file_copy_finish(SpiceMainChannel *channel, + GAsyncResult *result, + GError **error) +{ + GTask *task = G_TASK(result);; + + g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE); + g_return_val_if_fail(g_task_is_valid(task, channel), FALSE); + + return g_task_propagate_boolean(task, error); +} + + + +static void +spice_file_transfer_task_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(object); + + switch (property_id) + { + case PROP_TASK_ID: + g_value_set_uint(value, self->id); + break; + case PROP_TASK_FILE: + g_value_set_object(value, self->file); + break; + case PROP_TASK_PROGRESS: + g_value_set_double(value, spice_file_transfer_task_get_progress(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +spice_file_transfer_task_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(object); + + switch (property_id) + { + case PROP_TASK_ID: + self->id = g_value_get_uint(value); + break; + case PROP_TASK_FILE: + self->file = g_value_dup_object(value); + break; + case PROP_TASK_CHANNEL: + self->channel = g_value_dup_object(value); + break; + case PROP_TASK_CANCELLABLE: + self->cancellable = g_value_dup_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +spice_file_transfer_task_dispose(GObject *object) +{ + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(object); + + g_clear_object(&self->file); + + G_OBJECT_CLASS(spice_file_transfer_task_parent_class)->dispose(object); +} + +static void +spice_file_transfer_task_finalize(GObject *object) +{ + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(object); + + g_free(self->buffer); + + G_OBJECT_CLASS(spice_file_transfer_task_parent_class)->finalize(object); +} + +static void +spice_file_transfer_task_constructed(GObject *object) +{ + SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(object); + + if (spice_util_get_debug()) { + gchar *basename = g_file_get_basename(self->file); + self->start_time = g_get_monotonic_time(); + self->last_update = self->start_time; + + SPICE_DEBUG("transfer of file %s has started", basename); + g_free(basename); + } +} + +static void +spice_file_transfer_task_class_init(SpiceFileTransferTaskClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = spice_file_transfer_task_get_property; + object_class->set_property = spice_file_transfer_task_set_property; + object_class->finalize = spice_file_transfer_task_finalize; + object_class->dispose = spice_file_transfer_task_dispose; + object_class->constructed = spice_file_transfer_task_constructed; + + /** + * SpiceFileTransferTask:id: + * + * The ID of the file transfer task + * + * Since: 0.31 + **/ + g_object_class_install_property(object_class, PROP_TASK_ID, + g_param_spec_uint("id", + "id", + "The id of the task", + 0, G_MAXUINT, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceFileTransferTask:channel: + * + * The main channel that owns the file transfer task + * + * Since: 0.31 + **/ + g_object_class_install_property(object_class, PROP_TASK_CHANNEL, + g_param_spec_object("channel", + "channel", + "The channel transferring the file", + SPICE_TYPE_MAIN_CHANNEL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceFileTransferTask:cancellable: + * + * A cancellable object used to cancel the file transfer + * + * Since: 0.31 + **/ + g_object_class_install_property(object_class, PROP_TASK_CANCELLABLE, + g_param_spec_object("cancellable", + "cancellable", + "The object used to cancel the task", + G_TYPE_CANCELLABLE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceFileTransferTask:file: + * + * The file that is being transferred in this file transfer task + * + * Since: 0.31 + **/ + g_object_class_install_property(object_class, PROP_TASK_FILE, + g_param_spec_object("file", + "File", + "The file being transferred", + G_TYPE_FILE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceFileTransferTask:progress: + * + * The current state of the file transfer. This value indicates a + * percentage, and ranges from 0 to 100. Listen for change notifications on + * this property to be updated whenever the file transfer progress changes. + * + * Since: 0.31 + **/ + g_object_class_install_property(object_class, PROP_TASK_PROGRESS, + g_param_spec_double("progress", + "Progress", + "The percentage of the file transferred", + 0.0, 100.0, 0.0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceFileTransferTask::finished: + * @task: the file transfer task that emitted the signal + * @error: (transfer none): the error state of the transfer. Will be %NULL + * if the file transfer was successful. + * + * The #SpiceFileTransferTask::finished signal is emitted when the file + * transfer has completed transferring to the guest. + * + * Since: 0.31 + **/ + task_signals[SIGNAL_FINISHED] = g_signal_new("finished", SPICE_TYPE_FILE_TRANSFER_TASK, + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + G_TYPE_ERROR); +} + +static void +spice_file_transfer_task_init(SpiceFileTransferTask *self) +{ + self->buffer = g_malloc0(FILE_XFER_CHUNK_SIZE); +} + +static SpiceFileTransferTask * +spice_file_transfer_task_new(SpiceMainChannel *channel, GFile *file, GCancellable *cancellable) +{ + static uint32_t xfer_id = 0; /* Used to identify task id */ + + return g_object_new(SPICE_TYPE_FILE_TRANSFER_TASK, + "id", xfer_id++, + "file", file, + "channel", channel, + "cancellable", cancellable, + NULL); +} + +/** + * spice_file_transfer_task_get_progress: + * @self: a file transfer task + * + * Convenience function for retrieving the current progress of this file + * transfer task. + * + * Returns: A percentage value between 0 and 100 + * + * Since: 0.31 + **/ +double spice_file_transfer_task_get_progress(SpiceFileTransferTask *self) +{ + if (self->file_size == 0) + return 0.0; + + return (double)self->read_bytes / self->file_size; +} + +/** + * spice_file_transfer_task_cancel: + * @self: a file transfer task + * + * Cancels the file transfer task. Note that depending on how the file transfer + * was initiated, multiple file transfer tasks may share a single + * #SpiceFileTransferTask::cancellable object, so canceling one task may result + * in the cancellation of other tasks. + * + * Since: 0.31 + **/ +void spice_file_transfer_task_cancel(SpiceFileTransferTask *self) +{ + g_cancellable_cancel(self->cancellable); +} + +/** + * spice_file_transfer_task_get_filename: + * @self: a file transfer task + * + * Gets the name of the file being transferred in this task + * + * Returns: (transfer none): The basename of the file + * + * Since: 0.31 + **/ +char* spice_file_transfer_task_get_filename(SpiceFileTransferTask *self) +{ + return g_file_get_basename(self->file); +} diff --git a/src/channel-main.h b/src/channel-main.h new file mode 100644 index 0000000..3fe8df1 --- /dev/null +++ b/src/channel-main.h @@ -0,0 +1,116 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_MAIN_CHANNEL_H__ +#define __SPICE_CLIENT_MAIN_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_MAIN_CHANNEL (spice_main_channel_get_type()) +#define SPICE_MAIN_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_MAIN_CHANNEL, SpiceMainChannel)) +#define SPICE_MAIN_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_MAIN_CHANNEL, SpiceMainChannelClass)) +#define SPICE_IS_MAIN_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_MAIN_CHANNEL)) +#define SPICE_IS_MAIN_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_MAIN_CHANNEL)) +#define SPICE_MAIN_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_MAIN_CHANNEL, SpiceMainChannelClass)) + +typedef struct _SpiceMainChannel SpiceMainChannel; +typedef struct _SpiceMainChannelClass SpiceMainChannelClass; +typedef struct _SpiceMainChannelPrivate SpiceMainChannelPrivate; + +/** + * SpiceMainChannel: + * + * The #SpiceMainChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceMainChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceMainChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceMainChannelClass: + * @parent_class: Parent class. + * @mouse_update: Signal class handler for the #SpiceMainChannel::mouse-update signal. + * @agent_update: Signal class handler for the #SpiceMainChannel::agent-update signal. + * + * Class structure for #SpiceMainChannel. + */ +struct _SpiceMainChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*mouse_update)(SpiceChannel *channel); + void (*agent_update)(SpiceChannel *channel); + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_main_channel_get_type(void); + +void spice_main_set_display(SpiceMainChannel *channel, int id, + int x, int y, int width, int height); +void spice_main_update_display(SpiceMainChannel *channel, int id, + int x, int y, int width, int height, gboolean update); +void spice_main_set_display_enabled(SpiceMainChannel *channel, int id, gboolean enabled); +void spice_main_update_display_enabled(SpiceMainChannel *channel, int id, gboolean enabled, gboolean update); +gboolean spice_main_send_monitor_config(SpiceMainChannel *channel); + +void spice_main_clipboard_selection_grab(SpiceMainChannel *channel, guint selection, guint32 *types, int ntypes); +void spice_main_clipboard_selection_release(SpiceMainChannel *channel, guint selection); +void spice_main_clipboard_selection_notify(SpiceMainChannel *channel, guint selection, guint32 type, const guchar *data, size_t size); +void spice_main_clipboard_selection_request(SpiceMainChannel *channel, guint selection, guint32 type); + +gboolean spice_main_agent_test_capability(SpiceMainChannel *channel, guint32 cap); +void spice_main_file_copy_async(SpiceMainChannel *channel, + GFile **sources, + GFileCopyFlags flags, + GCancellable *cancellable, + GFileProgressCallback progress_callback, + gpointer progress_callback_data, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean spice_main_file_copy_finish(SpiceMainChannel *channel, + GAsyncResult *result, + GError **error); + +void spice_main_request_mouse_mode(SpiceMainChannel *channel, int mode); + +#ifndef SPICE_DISABLE_DEPRECATED +SPICE_DEPRECATED_FOR(spice_main_clipboard_selection_grab) +void spice_main_clipboard_grab(SpiceMainChannel *channel, guint32 *types, int ntypes); +SPICE_DEPRECATED_FOR(spice_main_clipboard_selection_release) +void spice_main_clipboard_release(SpiceMainChannel *channel); +SPICE_DEPRECATED_FOR(spice_main_clipboard_selection_notify) +void spice_main_clipboard_notify(SpiceMainChannel *channel, guint32 type, const guchar *data, size_t size); +SPICE_DEPRECATED_FOR(spice_main_clipboard_selection_request) +void spice_main_clipboard_request(SpiceMainChannel *channel, guint32 type); +#endif + +G_END_DECLS + +#endif /* __SPICE_CLIENT_MAIN_CHANNEL_H__ */ diff --git a/src/channel-playback-priv.h b/src/channel-playback-priv.h new file mode 100644 index 0000000..aa33d2c --- /dev/null +++ b/src/channel-playback-priv.h @@ -0,0 +1,24 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_PLAYBACK_CHANNEL_PRIV_H__ +#define __SPICE_CLIENT_PLAYBACK_CHANNEL_PRIV_H__ + +gboolean spice_playback_channel_is_active(SpicePlaybackChannel *channel); +guint32 spice_playback_channel_get_latency(SpicePlaybackChannel *channel); +void spice_playback_channel_sync_latency(SpicePlaybackChannel *channel); +#endif diff --git a/src/channel-playback.c b/src/channel-playback.c new file mode 100644 index 0000000..39c2178 --- /dev/null +++ b/src/channel-playback.c @@ -0,0 +1,503 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" +#include "spice-session-priv.h" + +#include "spice-marshal.h" + +#include "common/snd_codec.h" +#include "channel-playback-priv.h" + +/** + * SECTION:channel-playback + * @short_description: audio stream for playback + * @title: Playback Channel + * @section_id: + * @see_also: #SpiceChannel, and #SpiceAudio + * @stability: Stable + * @include: spice-client.h + * + * #SpicePlaybackChannel class handles an audio playback stream. The + * audio data is received via #SpicePlaybackChannel::playback-data + * signal, and is controlled by the guest with + * #SpicePlaybackChannel::playback-stop and + * #SpicePlaybackChannel::playback-start signal events. + * + * Note: You may be interested to let the #SpiceAudio class play and + * record audio channels for your application. + */ + +#define SPICE_PLAYBACK_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PLAYBACK_CHANNEL, SpicePlaybackChannelPrivate)) + +struct _SpicePlaybackChannelPrivate { + int mode; + SndCodec codec; + guint32 frame_count; + guint32 last_time; + guint8 nchannels; + guint16 *volume; + guint8 mute; + gboolean is_active; + guint32 latency; + guint32 min_latency; +}; + +G_DEFINE_TYPE(SpicePlaybackChannel, spice_playback_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_NCHANNELS, + PROP_VOLUME, + PROP_MUTE, + PROP_MIN_LATENCY, +}; + +/* Signals */ +enum { + SPICE_PLAYBACK_START, + SPICE_PLAYBACK_DATA, + SPICE_PLAYBACK_STOP, + SPICE_PLAYBACK_GET_DELAY, + + SPICE_PLAYBACK_LAST_SIGNAL, +}; + +static guint signals[SPICE_PLAYBACK_LAST_SIGNAL]; +static void channel_set_handlers(SpiceChannelClass *klass); + +/* ------------------------------------------------------------------ */ + +#define SPICE_PLAYBACK_DEFAULT_LATENCY_MS 200 + +static void spice_playback_channel_reset_capabilities(SpiceChannel *channel) +{ + if (!g_getenv("SPICE_DISABLE_CELT")) + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_PLAYBACK_CAP_CELT_0_5_1); + if (!g_getenv("SPICE_DISABLE_OPUS")) + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_PLAYBACK_CAP_OPUS); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_PLAYBACK_CAP_VOLUME); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_PLAYBACK_CAP_LATENCY); +} + +static void spice_playback_channel_init(SpicePlaybackChannel *channel) +{ + channel->priv = SPICE_PLAYBACK_CHANNEL_GET_PRIVATE(channel); + + spice_playback_channel_reset_capabilities(SPICE_CHANNEL(channel)); +} + +static void spice_playback_channel_finalize(GObject *obj) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(obj)->priv; + + snd_codec_destroy(&c->codec); + + g_clear_pointer(&c->volume, g_free); + + if (G_OBJECT_CLASS(spice_playback_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_playback_channel_parent_class)->finalize(obj); +} + +static void spice_playback_channel_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpicePlaybackChannel *channel = SPICE_PLAYBACK_CHANNEL(gobject); + SpicePlaybackChannelPrivate *c = channel->priv; + + switch (prop_id) { + case PROP_VOLUME: + g_value_set_pointer(value, c->volume); + break; + case PROP_NCHANNELS: + g_value_set_uint(value, c->nchannels); + break; + case PROP_MUTE: + g_value_set_boolean(value, c->mute); + break; + case PROP_MIN_LATENCY: + g_value_set_uint(value, c->min_latency); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_playback_channel_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_VOLUME: + /* TODO: request guest volume change */ + break; + case PROP_MUTE: + /* TODO: request guest mute change */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +/* main or coroutine context */ +static void spice_playback_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + + snd_codec_destroy(&c->codec); + g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_STOP], 0); + c->is_active = FALSE; + + SPICE_CHANNEL_CLASS(spice_playback_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_playback_channel_finalize; + gobject_class->get_property = spice_playback_channel_get_property; + gobject_class->set_property = spice_playback_channel_set_property; + + channel_class->channel_reset = spice_playback_channel_reset; + channel_class->channel_reset_capabilities = spice_playback_channel_reset_capabilities; + + g_object_class_install_property + (gobject_class, PROP_NCHANNELS, + g_param_spec_uint("nchannels", + "Number of Channels", + "Number of Channels", + 0, G_MAXUINT8, 2, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_VOLUME, + g_param_spec_pointer("volume", + "Playback volume", + "Playback volume", + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_MUTE, + g_param_spec_boolean("mute", + "Mute", + "Mute", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (gobject_class, PROP_MIN_LATENCY, + g_param_spec_uint("min-latency", + "Playback min buffer size (ms)", + "Playback min buffer size (ms)", + 0, G_MAXUINT32, SPICE_PLAYBACK_DEFAULT_LATENCY_MS, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + /** + * SpicePlaybackChannel::playback-start: + * @channel: the #SpicePlaybackChannel that emitted the signal + * @format: a #SPICE_AUDIO_FMT + * @channels: number of channels + * @rate: audio rate + * @latency: minimum playback latency in ms + * + * Notify when the playback should start, and provide audio format + * characteristics. + **/ + signals[SPICE_PLAYBACK_START] = + g_signal_new("playback-start", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpicePlaybackChannelClass, playback_start), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT_INT, + G_TYPE_NONE, + 3, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + + /** + * SpicePlaybackChannel::playback-data: + * @channel: the #SpicePlaybackChannel that emitted the signal + * @data: pointer to audio data + * @data_size: size in byte of @data + * + * Provide audio data to be played. + **/ + signals[SPICE_PLAYBACK_DATA] = + g_signal_new("playback-data", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpicePlaybackChannelClass, playback_data), + NULL, NULL, + g_cclosure_user_marshal_VOID__POINTER_INT, + G_TYPE_NONE, + 2, + G_TYPE_POINTER, G_TYPE_INT); + + /** + * SpicePlaybackChannel::playback-stop: + * @channel: the #SpicePlaybackChannel that emitted the signal + * + * Notify when the playback should stop. + **/ + signals[SPICE_PLAYBACK_STOP] = + g_signal_new("playback-stop", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpicePlaybackChannelClass, playback_stop), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * SpicePlaybackChannel::playback-get-delay: + * @channel: the #SpicePlaybackChannel that emitted the signal + * + * Notify when the current playback delay is requested + **/ + signals[SPICE_PLAYBACK_GET_DELAY] = + g_signal_new("playback-get-delay", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private(klass, sizeof(SpicePlaybackChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* ------------------------------------------------------------------ */ + +/* coroutine context */ +static void playback_handle_data(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgPlaybackPacket *packet = spice_msg_in_parsed(in); + +#ifdef DEBUG + CHANNEL_DEBUG(channel, "%s: time %u data %p size %d", __FUNCTION__, + packet->time, packet->data, packet->data_size); +#endif + + if (c->last_time > packet->time) + g_warn_if_reached(); + + c->last_time = packet->time; + + uint8_t *data = packet->data; + int n = packet->data_size; + uint8_t pcm[SND_CODEC_MAX_FRAME_SIZE * 2 * 2]; + + if (c->mode != SPICE_AUDIO_DATA_MODE_RAW) { + n = sizeof(pcm); + data = pcm; + + if (snd_codec_decode(c->codec, packet->data, packet->data_size, + pcm, &n) != SND_CODEC_OK) { + g_warning("snd_codec_decode() error"); + return; + } + } + + g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_DATA], 0, data, n); + + if ((c->frame_count++ % 100) == 0) { + g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_GET_DELAY], 0); + } +} + +/* coroutine context */ +static void playback_handle_mode(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgPlaybackMode *mode = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "%s: time %u mode %u data %p size %u", __FUNCTION__, + mode->time, mode->mode, mode->data, mode->data_size); + + c->mode = mode->mode; + switch (c->mode) { + case SPICE_AUDIO_DATA_MODE_RAW: + case SPICE_AUDIO_DATA_MODE_CELT_0_5_1: + case SPICE_AUDIO_DATA_MODE_OPUS: + break; + default: + g_warning("%s: unhandled mode", __FUNCTION__); + break; + } +} + +/* coroutine context */ +static void playback_handle_start(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgPlaybackStart *start = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "%s: fmt %u channels %u freq %u time %u", __FUNCTION__, + start->format, start->channels, start->frequency, start->time); + + c->frame_count = 0; + c->last_time = start->time; + c->is_active = TRUE; + c->min_latency = SPICE_PLAYBACK_DEFAULT_LATENCY_MS; + snd_codec_destroy(&c->codec); + + if (c->mode != SPICE_AUDIO_DATA_MODE_RAW) { + if (snd_codec_create(&c->codec, c->mode, start->frequency, SND_CODEC_DECODE) != SND_CODEC_OK) { + g_warning("create decoder failed"); + return; + } + } + g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_START], 0, + start->format, start->channels, start->frequency); +} + +/* coroutine context */ +static void playback_handle_stop(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + + g_coroutine_signal_emit(channel, signals[SPICE_PLAYBACK_STOP], 0); + c->is_active = FALSE; +} + +/* coroutine context */ +static void playback_handle_set_volume(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgAudioVolume *vol = spice_msg_in_parsed(in); + + if (vol->nchannels == 0) { + g_warning("spice-server send audio-volume-msg with 0 channels"); + return; + } + + g_free(c->volume); + c->nchannels = vol->nchannels; + c->volume = g_new(guint16, c->nchannels); + memcpy(c->volume, vol->volume, sizeof(guint16) * c->nchannels); + g_coroutine_object_notify(G_OBJECT(channel), "volume"); +} + +/* coroutine context */ +static void playback_handle_set_mute(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgAudioMute *m = spice_msg_in_parsed(in); + + c->mute = m->mute; + g_coroutine_object_notify(G_OBJECT(channel), "mute"); +} + +/* coroutine context */ +static void playback_handle_set_latency(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + SpiceMsgPlaybackLatency *msg = spice_msg_in_parsed(in); + + c->min_latency = msg->latency_ms; + SPICE_DEBUG("%s: notify latency update %u", __FUNCTION__, c->min_latency); + g_coroutine_object_notify(G_OBJECT(channel), "min-latency"); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_PLAYBACK_DATA ] = playback_handle_data, + [ SPICE_MSG_PLAYBACK_MODE ] = playback_handle_mode, + [ SPICE_MSG_PLAYBACK_START ] = playback_handle_start, + [ SPICE_MSG_PLAYBACK_STOP ] = playback_handle_stop, + [ SPICE_MSG_PLAYBACK_VOLUME ] = playback_handle_set_volume, + [ SPICE_MSG_PLAYBACK_MUTE ] = playback_handle_set_mute, + [ SPICE_MSG_PLAYBACK_LATENCY ] = playback_handle_set_latency, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +/** + * spice_playback_channel_set_delay: + * @channel: a #SpicePlaybackChannel + * @delay_ms: the delay in ms + * + * Adjust the multimedia time according to the delay. + **/ +void spice_playback_channel_set_delay(SpicePlaybackChannel *channel, guint32 delay_ms) +{ + SpicePlaybackChannelPrivate *c; + SpiceSession *session; + + g_return_if_fail(SPICE_IS_PLAYBACK_CHANNEL(channel)); + + CHANNEL_DEBUG(channel, "playback set_delay %u ms", delay_ms); + + c = channel->priv; + c->latency = delay_ms; + + session = spice_channel_get_session(SPICE_CHANNEL(channel)); + if (session) { + spice_session_set_mm_time(session, c->last_time - delay_ms); + } else { + CHANNEL_DEBUG(channel, "channel detached from session, mm time skipped"); + } +} + +G_GNUC_INTERNAL +gboolean spice_playback_channel_is_active(SpicePlaybackChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_PLAYBACK_CHANNEL(channel), FALSE); + return channel->priv->is_active; +} + +G_GNUC_INTERNAL +guint32 spice_playback_channel_get_latency(SpicePlaybackChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_PLAYBACK_CHANNEL(channel), 0); + if (!channel->priv->is_active) { + return 0; + } + return channel->priv->latency; +} + +G_GNUC_INTERNAL +void spice_playback_channel_sync_latency(SpicePlaybackChannel *channel) +{ + g_return_if_fail(SPICE_IS_PLAYBACK_CHANNEL(channel)); + g_return_if_fail(channel->priv->is_active); + SPICE_DEBUG("%s: notify latency update %u", __FUNCTION__, channel->priv->min_latency); + g_coroutine_object_notify(G_OBJECT(SPICE_CHANNEL(channel)), "min-latency"); +} diff --git a/src/channel-playback.h b/src/channel-playback.h new file mode 100644 index 0000000..e61409d --- /dev/null +++ b/src/channel-playback.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_PLAYBACK_CHANNEL_H__ +#define __SPICE_CLIENT_PLAYBACK_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_PLAYBACK_CHANNEL (spice_playback_channel_get_type()) +#define SPICE_PLAYBACK_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_PLAYBACK_CHANNEL, SpicePlaybackChannel)) +#define SPICE_PLAYBACK_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_PLAYBACK_CHANNEL, SpicePlaybackChannelClass)) +#define SPICE_IS_PLAYBACK_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_PLAYBACK_CHANNEL)) +#define SPICE_IS_PLAYBACK_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_PLAYBACK_CHANNEL)) +#define SPICE_PLAYBACK_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_PLAYBACK_CHANNEL, SpicePlaybackChannelClass)) + +typedef struct _SpicePlaybackChannel SpicePlaybackChannel; +typedef struct _SpicePlaybackChannelClass SpicePlaybackChannelClass; +typedef struct _SpicePlaybackChannelPrivate SpicePlaybackChannelPrivate; + +/** + * SpicePlaybackChannel: + * + * The #SpicePlaybackChannel struct is opaque and should not be accessed directly. + */ +struct _SpicePlaybackChannel { + SpiceChannel parent; + + /*< private >*/ + SpicePlaybackChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpicePlaybackChannelClass: + * @parent_class: Parent class. + * @playback_start: Signal class handler for the #SpicePlaybackChannel::playback-start signal. + * @playback_data: Signal class handler for the #SpicePlaybackChannel::playback-data signal. + * @playback_stop: Signal class handler for the #SpicePlaybackChannel::playback-stop signal. + * + * Class structure for #SpicePlaybackChannel. + */ +struct _SpicePlaybackChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*playback_start)(SpicePlaybackChannel *channel, + gint format, gint channels, gint freq); + void (*playback_data)(SpicePlaybackChannel *channel, gpointer *data, gint size); + void (*playback_stop)(SpicePlaybackChannel *channel); + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_playback_channel_get_type(void); +void spice_playback_channel_set_delay(SpicePlaybackChannel *channel, guint32 delay_ms); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_PLAYBACK_CHANNEL_H__ */ diff --git a/src/channel-port.c b/src/channel-port.c new file mode 100644 index 0000000..d922e4b --- /dev/null +++ b/src/channel-port.c @@ -0,0 +1,361 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" +#include "spice-marshal.h" + +/** + * SECTION:channel-port + * @short_description: private communication channel + * @title: Port Channel + * @section_id: + * @see_also: #SpiceChannel + * @stability: Stable + * @include: spice-client.h + * + * A Spice port channel carry arbitrary data between the Spice client + * and the Spice server. It may be used to provide additional + * services on top of a Spice connection. For example, a channel can + * be associated with the qemu monitor for the client to interact + * with it, just like any qemu chardev. Or it may be used with + * various protocols, such as the Spice Controller. + * + * A port kind is identified simply by a fqdn, such as + * org.qemu.monitor, org.spice.spicy.test or org.ovirt.controller... + * + * Once connected and initialized, the client may read the name of the + * port via SpicePortChannel:port-name. + + * When the other end of the port is ready, + * SpicePortChannel:port-opened is set to %TRUE and you can start + * receiving data via the signal SpicePortChannel::port-data, or + * sending data via spice_port_write_async(). + * + * Since: 0.15 + */ + +#define SPICE_PORT_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PORT_CHANNEL, SpicePortChannelPrivate)) + +struct _SpicePortChannelPrivate { + gchar *name; + gboolean opened; +}; + +G_DEFINE_TYPE(SpicePortChannel, spice_port_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_PORT_NAME, + PROP_PORT_OPENED, +}; + +/* Signals */ +enum { + SPICE_PORT_DATA, + SPICE_PORT_EVENT, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL]; +static void channel_set_handlers(SpiceChannelClass *klass); + +static void spice_port_channel_init(SpicePortChannel *channel) +{ + channel->priv = SPICE_PORT_CHANNEL_GET_PRIVATE(channel); +} + +static void spice_port_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpicePortChannelPrivate *c = SPICE_PORT_CHANNEL(object)->priv; + + switch (prop_id) { + case PROP_PORT_NAME: + g_value_set_string(value, c->name); + break; + case PROP_PORT_OPENED: + g_value_set_boolean(value, c->opened); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void spice_port_channel_finalize(GObject *object) +{ + SpicePortChannelPrivate *c = SPICE_PORT_CHANNEL(object)->priv; + + g_free(c->name); + + if (G_OBJECT_CLASS(spice_port_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_port_channel_parent_class)->finalize(object); +} + +static void spice_port_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpicePortChannelPrivate *c = SPICE_PORT_CHANNEL(channel)->priv; + + g_clear_pointer(&c->name, g_free); + c->opened = FALSE; + + SPICE_CHANNEL_CLASS(spice_port_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_port_channel_class_init(SpicePortChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_port_channel_finalize; + gobject_class->get_property = spice_port_get_property; + channel_class->channel_reset = spice_port_channel_reset; + + g_object_class_install_property + (gobject_class, PROP_PORT_NAME, + g_param_spec_string("port-name", + "Port name", + "Port name", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_PORT_OPENED, + g_param_spec_boolean("port-opened", + "Port opened", + "Port opened", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * SpicePortChannel::port-data: + * @channel: the channel that emitted the signal + * @data: the data received + * @size: number of bytes read + * + * The #SpicePortChannel::port-data signal is emitted when new + * port data is received. + * Since: 0.15 + **/ + signals[SPICE_PORT_DATA] = + g_signal_new("port-data", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_user_marshal_VOID__POINTER_INT, + G_TYPE_NONE, + 2, + G_TYPE_POINTER, G_TYPE_INT); + + + /** + * SpicePortChannel::port-event: + * @channel: the channel that emitted the signal + * @event: the event received + * @size: number of bytes read + * + * The #SpicePortChannel::port-event signal is emitted when new + * port event is received. + * Since: 0.15 + **/ + signals[SPICE_PORT_EVENT] = + g_signal_new("port-event", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + + g_type_class_add_private(klass, sizeof(SpicePortChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + + +/* coroutine context */ +static void port_set_opened(SpicePortChannel *self, gboolean opened) +{ + SpicePortChannelPrivate *c = self->priv; + + if (c->opened == opened) + return; + + c->opened = opened; + g_coroutine_object_notify(G_OBJECT(self), "port-opened"); +} + +/* coroutine context */ +static void port_handle_init(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePortChannel *self = SPICE_PORT_CHANNEL(channel); + SpicePortChannelPrivate *c = self->priv; + SpiceMsgPortInit *init = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "init: %s %d", init->name, init->opened); + g_return_if_fail(init->name != NULL && *init->name != '\0'); + g_return_if_fail(c->name == NULL); + + c->name = g_strdup((gchar*)init->name); + + port_set_opened(self, init->opened); + if (init->opened) + g_coroutine_signal_emit(channel, signals[SPICE_PORT_EVENT], 0, SPICE_PORT_EVENT_OPENED); + + g_coroutine_object_notify(G_OBJECT(channel), "port-name"); +} + +/* coroutine context */ +static void port_handle_event(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePortChannel *self = SPICE_PORT_CHANNEL(channel); + SpiceMsgPortEvent *event = spice_msg_in_parsed(in); + + CHANNEL_DEBUG(channel, "port event: %d", event->event); + switch (event->event) { + case SPICE_PORT_EVENT_OPENED: + port_set_opened(self, true); + break; + case SPICE_PORT_EVENT_CLOSED: + port_set_opened(self, false); + break; + } + + g_coroutine_signal_emit(channel, signals[SPICE_PORT_EVENT], 0, event->event); +} + +/* coroutine context */ +static void port_handle_msg(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpicePortChannel *self = SPICE_PORT_CHANNEL(channel); + int size; + uint8_t *buf; + + buf = spice_msg_in_raw(in, &size); + CHANNEL_DEBUG(channel, "port %p got %d %p", channel, size, buf); + port_set_opened(self, true); + g_coroutine_signal_emit(channel, signals[SPICE_PORT_DATA], 0, buf, size); +} + +/** + * spice_port_write_async: + * @port: A #SpicePortChannel + * @buffer: (array length=count) (element-type guint8): the buffer + * containing the data to write + * @count: the number of bytes to write + * @cancellable: (allow-none): optional GCancellable object, NULL to ignore + * @callback: (scope async): callback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Request an asynchronous write of count bytes from @buffer into the + * @port. When the operation is finished @callback will be called. You + * can then call spice_port_write_finish() to get the result of + * the operation. + * + * Since: 0.15 + **/ +void spice_port_write_async(SpicePortChannel *self, + const void *buffer, gsize count, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpicePortChannelPrivate *c; + + g_return_if_fail(SPICE_IS_PORT_CHANNEL(self)); + g_return_if_fail(buffer != NULL); + c = self->priv; + + if (!c->opened) { + g_task_report_new_error(self, callback, + user_data, spice_port_write_async, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "The port is not opened"); + return; + } + + spice_vmc_write_async(SPICE_CHANNEL(self), buffer, count, + cancellable, callback, user_data); +} + +/** + * spice_port_write_finish: + * @port: a #SpicePortChannel + * @result: a #GAsyncResult + * @error: a #GError location to store the error occurring, or %NULL + * to ignore + * + * Finishes a port write operation. + * + * Returns: a #gssize containing the number of bytes written to the stream. + * Since: 0.15 + **/ +gssize spice_port_write_finish(SpicePortChannel *self, + GAsyncResult *result, GError **error) +{ + g_return_val_if_fail(SPICE_IS_PORT_CHANNEL(self), -1); + + return spice_vmc_write_finish(SPICE_CHANNEL(self), result, error); +} + +/** + * spice_port_event: + * @port: a #SpicePortChannel + * @event: a SPICE_PORT_EVENT value + * + * Send an event to the port. + * + * Note: The values SPICE_PORT_EVENT_CLOSED and + * SPICE_PORT_EVENT_OPENED are managed by the channel connection + * state. + * + * Since: 0.15 + **/ +void spice_port_event(SpicePortChannel *self, guint8 event) +{ + SpiceMsgcPortEvent e; + SpiceMsgOut *msg; + + g_return_if_fail(SPICE_IS_PORT_CHANNEL(self)); + g_return_if_fail(event > SPICE_PORT_EVENT_CLOSED); + + msg = spice_msg_out_new(SPICE_CHANNEL(self), SPICE_MSGC_PORT_EVENT); + e.event = event; + msg->marshallers->msgc_port_event(msg->marshaller, &e); + spice_msg_out_send(msg); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_PORT_INIT ] = port_handle_init, + [ SPICE_MSG_PORT_EVENT ] = port_handle_event, + [ SPICE_MSG_SPICEVMC_DATA ] = port_handle_msg, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} diff --git a/src/channel-port.h b/src/channel-port.h new file mode 100644 index 0000000..8fc19cc --- /dev/null +++ b/src/channel-port.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_PORT_CHANNEL_H__ +#define __SPICE_CLIENT_PORT_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include "spice-channel.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_PORT_CHANNEL (spice_port_channel_get_type()) +#define SPICE_PORT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_PORT_CHANNEL, SpicePortChannel)) +#define SPICE_PORT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_PORT_CHANNEL, SpicePortChannelClass)) +#define SPICE_IS_PORT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_PORT_CHANNEL)) +#define SPICE_IS_PORT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_PORT_CHANNEL)) +#define SPICE_PORT_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_PORT_CHANNEL, SpicePortChannelClass)) + +typedef struct _SpicePortChannel SpicePortChannel; +typedef struct _SpicePortChannelClass SpicePortChannelClass; +typedef struct _SpicePortChannelPrivate SpicePortChannelPrivate; + +/** + * SpicePortChannel: + * + * The #SpicePortChannel struct is opaque and should not be accessed directly. + */ +struct _SpicePortChannel { + SpiceChannel parent; + + /*< private >*/ + SpicePortChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpicePortChannelClass: + * @parent_class: Parent class. + * + * Class structure for #SpicePortChannel. + */ +struct _SpicePortChannelClass { + SpiceChannelClass parent_class; + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_port_channel_get_type(void); + +void spice_port_write_async(SpicePortChannel *port, + const void *buffer, gsize count, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gssize spice_port_write_finish(SpicePortChannel *port, + GAsyncResult *result, GError **error); +void spice_port_event(SpicePortChannel *port, guint8 event); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_PORT_CHANNEL_H__ */ diff --git a/src/channel-record.c b/src/channel-record.c new file mode 100644 index 0000000..c1d9afa --- /dev/null +++ b/src/channel-record.c @@ -0,0 +1,479 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" + +#include "spice-marshal.h" +#include "spice-session-priv.h" + +#include "common/snd_codec.h" + +/** + * SECTION:channel-record + * @short_description: audio stream for recording + * @title: Record Channel + * @section_id: + * @see_also: #SpiceChannel, and #SpiceAudio + * @stability: Stable + * @include: spice-client.h + * + * #SpiceRecordChannel class handles an audio recording stream. The + * audio stream should start when #SpiceRecordChannel::record-start is + * emitted and should be stopped when #SpiceRecordChannel::record-stop + * is received. + * + * The audio is sent to the guest by calling spice_record_send_data() + * with the recorded PCM data. + * + * Note: You may be interested to let the #SpiceAudio class play and + * record audio channels for your application. + */ + +#define SPICE_RECORD_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_RECORD_CHANNEL, SpiceRecordChannelPrivate)) + +struct _SpiceRecordChannelPrivate { + int mode; + gboolean started; + SndCodec codec; + gsize frame_bytes; + guint8 *last_frame; + gsize last_frame_current; + guint8 nchannels; + guint16 *volume; + guint8 mute; +}; + +G_DEFINE_TYPE(SpiceRecordChannel, spice_record_channel, SPICE_TYPE_CHANNEL) + +/* Properties */ +enum { + PROP_0, + PROP_NCHANNELS, + PROP_VOLUME, + PROP_MUTE, +}; + +/* Signals */ +enum { + SPICE_RECORD_START, + SPICE_RECORD_STOP, + + SPICE_RECORD_LAST_SIGNAL, +}; + +static guint signals[SPICE_RECORD_LAST_SIGNAL]; + +static void channel_set_handlers(SpiceChannelClass *klass); + +/* ------------------------------------------------------------------ */ + +static void spice_record_channel_reset_capabilities(SpiceChannel *channel) +{ + if (!g_getenv("SPICE_DISABLE_CELT")) + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_RECORD_CAP_CELT_0_5_1); + if (!g_getenv("SPICE_DISABLE_OPUS")) + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_RECORD_CAP_OPUS); + spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_RECORD_CAP_VOLUME); +} + +static void spice_record_channel_init(SpiceRecordChannel *channel) +{ + channel->priv = SPICE_RECORD_CHANNEL_GET_PRIVATE(channel); + + spice_record_channel_reset_capabilities(SPICE_CHANNEL(channel)); +} + +static void spice_record_channel_finalize(GObject *obj) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(obj)->priv; + + g_clear_pointer(&c->last_frame, g_free); + + snd_codec_destroy(&c->codec); + + g_clear_pointer(&c->volume, g_free); + + if (G_OBJECT_CLASS(spice_record_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_record_channel_parent_class)->finalize(obj); +} + +static void spice_record_channel_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceRecordChannel *channel = SPICE_RECORD_CHANNEL(gobject); + SpiceRecordChannelPrivate *c = channel->priv; + + switch (prop_id) { + case PROP_VOLUME: + g_value_set_pointer(value, c->volume); + break; + case PROP_NCHANNELS: + g_value_set_uint(value, c->nchannels); + break; + case PROP_MUTE: + g_value_set_boolean(value, c->mute); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_record_channel_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_VOLUME: + /* TODO: request guest volume change */ + break; + case PROP_MUTE: + /* TODO: request guest mute change */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv; + + g_clear_pointer(&c->last_frame, g_free); + + g_coroutine_signal_emit(channel, signals[SPICE_RECORD_STOP], 0); + c->started = FALSE; + + snd_codec_destroy(&c->codec); + + SPICE_CHANNEL_CLASS(spice_record_channel_parent_class)->channel_reset(channel, migrating); +} + +static void spice_record_channel_class_init(SpiceRecordChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_record_channel_finalize; + gobject_class->get_property = spice_record_channel_get_property; + gobject_class->set_property = spice_record_channel_set_property; + channel_class->channel_reset = channel_reset; + channel_class->channel_reset_capabilities = spice_record_channel_reset_capabilities; + + g_object_class_install_property + (gobject_class, PROP_NCHANNELS, + g_param_spec_uint("nchannels", + "Number of Channels", + "Number of Channels", + 0, G_MAXUINT8, 2, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_VOLUME, + g_param_spec_pointer("volume", + "Record volume", + "Record volume", + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_MUTE, + g_param_spec_boolean("mute", + "Mute", + "Mute", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + /** + * SpiceRecordChannel::record-start: + * @channel: the #SpiceRecordChannel that emitted the signal + * @format: a #SPICE_AUDIO_FMT + * @channels: number of channels + * @rate: audio rate + * + * Notify when the recording should start, and provide audio format + * characteristics. + **/ + signals[SPICE_RECORD_START] = + g_signal_new("record-start", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceRecordChannelClass, record_start), + NULL, NULL, + g_cclosure_user_marshal_VOID__INT_INT_INT, + G_TYPE_NONE, + 3, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + + /** + * SpiceRecordChannel::record-stop: + * @channel: the #SpiceRecordChannel that emitted the signal + * + * Notify when the recording should stop. + **/ + signals[SPICE_RECORD_STOP] = + g_signal_new("record-stop", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceRecordChannelClass, record_stop), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private(klass, sizeof(SpiceRecordChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* main context */ +static void spice_record_mode(SpiceRecordChannel *channel, uint32_t time, + uint32_t mode, uint8_t *data, uint32_t data_size) +{ + SpiceMsgcRecordMode m = {0, }; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + m.mode = mode; + m.time = time; + m.data = data; + m.data_size = data_size; + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_RECORD_MODE); + msg->marshallers->msgc_record_mode(msg->marshaller, &m); + spice_msg_out_send(msg); +} + +static int spice_record_desired_mode(SpiceChannel *channel, int frequency) +{ + if (!g_getenv("SPICE_DISABLE_OPUS") && + snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, frequency) && + spice_channel_test_capability(channel, SPICE_RECORD_CAP_OPUS)) { + return SPICE_AUDIO_DATA_MODE_OPUS; + } else if (!g_getenv("SPICE_DISABLE_CELT") && + snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, frequency) && + spice_channel_test_capability(channel, SPICE_RECORD_CAP_CELT_0_5_1)) { + return SPICE_AUDIO_DATA_MODE_CELT_0_5_1; + } else { + return SPICE_AUDIO_DATA_MODE_RAW; + } +} + +/* main context */ +static void spice_record_start_mark(SpiceRecordChannel *channel, uint32_t time) +{ + SpiceMsgcRecordStartMark m = {0, }; + SpiceMsgOut *msg; + + g_return_if_fail(channel != NULL); + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + m.time = time; + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_RECORD_START_MARK); + msg->marshallers->msgc_record_start_mark(msg->marshaller, &m); + spice_msg_out_send(msg); +} + +/** + * spice_record_send_data: + * @channel: a #SpiceRecordChannel + * @data: PCM data + * @bytes: size of @data + * @time: stream timestamp + * + * Send recorded PCM data to the guest. + **/ +void spice_record_send_data(SpiceRecordChannel *channel, gpointer data, + gsize bytes, uint32_t time) +{ + SpiceRecordChannelPrivate *rc; + SpiceMsgcRecordPacket p = {0, }; + + g_return_if_fail(SPICE_IS_RECORD_CHANNEL(channel)); + rc = channel->priv; + if (rc->last_frame == NULL) { + CHANNEL_DEBUG(channel, "recording didn't start or was reset"); + return; + } + + g_return_if_fail(spice_channel_get_read_only(SPICE_CHANNEL(channel)) == FALSE); + + uint8_t *encode_buf = NULL; + + if (!rc->started) { + spice_record_mode(channel, time, rc->mode, NULL, 0); + spice_record_start_mark(channel, time); + rc->started = TRUE; + } + + if (rc->mode != SPICE_AUDIO_DATA_MODE_RAW) + encode_buf = g_alloca(SND_CODEC_MAX_COMPRESSED_BYTES); + + p.time = time; + + while (bytes > 0) { + gsize n; + int frame_size; + SpiceMsgOut *msg; + uint8_t *frame; + + if (rc->last_frame_current > 0) { + /* complete previous frame */ + n = MIN(bytes, rc->frame_bytes - rc->last_frame_current); + memcpy(rc->last_frame + rc->last_frame_current, data, n); + rc->last_frame_current += n; + if (rc->last_frame_current < rc->frame_bytes) + /* if the frame is still incomplete, return */ + break; + frame = rc->last_frame; + frame_size = rc->frame_bytes; + } else { + n = MIN(bytes, rc->frame_bytes); + frame_size = n; + frame = data; + } + + if (rc->last_frame_current == 0 && + n < rc->frame_bytes) { + /* start a new frame */ + memcpy(rc->last_frame, data, n); + rc->last_frame_current = n; + break; + } + + if (rc->mode != SPICE_AUDIO_DATA_MODE_RAW) { + int len = SND_CODEC_MAX_COMPRESSED_BYTES; + if (snd_codec_encode(rc->codec, frame, frame_size, encode_buf, &len) != SND_CODEC_OK) { + g_warning("encode failed"); + return; + } + frame = encode_buf; + frame_size = len; + } + + msg = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_RECORD_DATA); + msg->marshallers->msgc_record_data(msg->marshaller, &p); + spice_marshaller_add(msg->marshaller, frame, frame_size); + spice_msg_out_send(msg); + + if (rc->last_frame_current == rc->frame_bytes) + rc->last_frame_current = 0; + + bytes -= n; + data = (guint8*)data + n; + } +} + +/* ------------------------------------------------------------------ */ + +/* coroutine context */ +static void record_handle_start(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv; + SpiceMsgRecordStart *start = spice_msg_in_parsed(in); + int frame_size = SND_CODEC_MAX_FRAME_SIZE; + + c->mode = spice_record_desired_mode(channel, start->frequency); + + CHANNEL_DEBUG(channel, "%s: fmt %u channels %u freq %u", __FUNCTION__, + start->format, start->channels, start->frequency); + + g_return_if_fail(start->format == SPICE_AUDIO_FMT_S16); + + snd_codec_destroy(&c->codec); + + if (c->mode != SPICE_AUDIO_DATA_MODE_RAW) { + if (snd_codec_create(&c->codec, c->mode, start->frequency, SND_CODEC_ENCODE) != SND_CODEC_OK) { + g_warning("Failed to create encoder"); + return; + } + frame_size = snd_codec_frame_size(c->codec); + } + + g_free(c->last_frame); + c->frame_bytes = frame_size * 16 * start->channels / 8; + c->last_frame = g_malloc0(c->frame_bytes); + c->last_frame_current = 0; + + g_coroutine_signal_emit(channel, signals[SPICE_RECORD_START], 0, + start->format, start->channels, start->frequency); +} + +/* coroutine context */ +static void record_handle_stop(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceRecordChannelPrivate *rc = SPICE_RECORD_CHANNEL(channel)->priv; + + g_coroutine_signal_emit(channel, signals[SPICE_RECORD_STOP], 0); + rc->started = FALSE; +} + +/* coroutine context */ +static void record_handle_set_volume(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv; + SpiceMsgAudioVolume *vol = spice_msg_in_parsed(in); + + if (vol->nchannels == 0) { + g_warning("spice-server send audio-volume-msg with 0 channels"); + return; + } + + g_free(c->volume); + c->nchannels = vol->nchannels; + c->volume = g_new(guint16, c->nchannels); + memcpy(c->volume, vol->volume, sizeof(guint16) * c->nchannels); + g_coroutine_object_notify(G_OBJECT(channel), "volume"); +} + +/* coroutine context */ +static void record_handle_set_mute(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv; + SpiceMsgAudioMute *m = spice_msg_in_parsed(in); + + c->mute = m->mute; + g_coroutine_object_notify(G_OBJECT(channel), "mute"); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_RECORD_START ] = record_handle_start, + [ SPICE_MSG_RECORD_STOP ] = record_handle_stop, + [ SPICE_MSG_RECORD_VOLUME ] = record_handle_set_volume, + [ SPICE_MSG_RECORD_MUTE ] = record_handle_set_mute, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} diff --git a/src/channel-record.h b/src/channel-record.h new file mode 100644 index 0000000..c851421 --- /dev/null +++ b/src/channel-record.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_RECORD_CHANNEL_H__ +#define __SPICE_CLIENT_RECORD_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_RECORD_CHANNEL (spice_record_channel_get_type()) +#define SPICE_RECORD_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_RECORD_CHANNEL, SpiceRecordChannel)) +#define SPICE_RECORD_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_RECORD_CHANNEL, SpiceRecordChannelClass)) +#define SPICE_IS_RECORD_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_RECORD_CHANNEL)) +#define SPICE_IS_RECORD_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_RECORD_CHANNEL)) +#define SPICE_RECORD_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_RECORD_CHANNEL, SpiceRecordChannelClass)) + +typedef struct _SpiceRecordChannel SpiceRecordChannel; +typedef struct _SpiceRecordChannelClass SpiceRecordChannelClass; +typedef struct _SpiceRecordChannelPrivate SpiceRecordChannelPrivate; + +/** + * SpiceRecordChannel: + * + * The #SpiceRecordChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceRecordChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceRecordChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceRecordChannelClass: + * @parent_class: Parent class. + * @record_start: Signal class handler for the #SpiceRecordChannel::record-start signal. + * @record_stop: Signal class handler for the #SpiceRecordChannel::record-stop signal. + * @record_data: Unused (deprecated). + * + * Class structure for #SpiceRecordChannel. + */ +struct _SpiceRecordChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + void (*record_start)(SpiceRecordChannel *channel, + gint format, gint channels, gint freq); + void (*record_data)(SpiceRecordChannel *channel, gpointer *data, gint size); + void (*record_stop)(SpiceRecordChannel *channel); + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_record_channel_get_type(void); +void spice_record_send_data(SpiceRecordChannel *channel, gpointer data, + gsize bytes, guint32 time); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_RECORD_CHANNEL_H__ */ diff --git a/src/channel-smartcard.c b/src/channel-smartcard.c new file mode 100644 index 0000000..e086e92 --- /dev/null +++ b/src/channel-smartcard.c @@ -0,0 +1,571 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#ifdef USE_SMARTCARD_012 +#include +#endif + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-channel-priv.h" +#include "smartcard-manager.h" +#include "smartcard-manager-priv.h" +#include "spice-session-priv.h" + +/** + * SECTION:channel-smartcard + * @short_description: smartcard authentication + * @title: Smartcard Channel + * @section_id: + * @see_also: #SpiceSmartcardManager, #SpiceSession + * @stability: Stable + * @include: spice-client.h + * + * The Spice protocol defines a set of messages to forward smartcard + * information from the Spice client to the VM. This channel handles + * these messages. While it's mainly focus on smartcard readers and + * smartcards, it's also possible to use it with a software smartcard + * (ie a set of 3 certificates from the client machine). + * This class doesn't provide useful methods, see #SpiceSession properties + * for a way to enable/disable this channel, and #SpiceSmartcardManager + * if you want to detect smartcard reader hotplug/unplug, and smartcard + * insertion/removal. + */ + +#define SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_SMARTCARD_CHANNEL, SpiceSmartcardChannelPrivate)) + +struct _SpiceSmartcardChannelMessage { +#ifdef USE_SMARTCARD + VSCMsgType message_type; +#endif + SpiceMsgOut *message; +}; +typedef struct _SpiceSmartcardChannelMessage SpiceSmartcardChannelMessage; + + +struct _SpiceSmartcardChannelPrivate { + /* track readers that have been added but for which we didn't receive + * an ack from the spice server yet. We rely on the fact that the + * readers in this list are ordered by the time we sent the request to + * the server. When we get an ack from the server for a reader addition, + * we can pop the 1st entry to get the reader the ack corresponds to. */ + GList *pending_reader_additions; + + /* used to removals of readers that were not ack'ed yet by the spice + * server */ + GHashTable *pending_reader_removals; + + /* used to track card insertions on readers that were not ack'ed yet + * by the spice server */ + GHashTable *pending_card_insertions; + + /* next commands to be sent to the spice server. This is needed since + * we have to wait for a command answer before sending the next one + */ + GQueue *message_queue; + + /* message that is currently being processed by the spice server (ie last + * message that was sent to the server) + */ + SpiceSmartcardChannelMessage *in_flight_message; +}; + +G_DEFINE_TYPE(SpiceSmartcardChannel, spice_smartcard_channel, SPICE_TYPE_CHANNEL) + +enum { + + SPICE_SMARTCARD_LAST_SIGNAL, +}; + +static void spice_smartcard_channel_up(SpiceChannel *channel); +static void handle_smartcard_msg(SpiceChannel *channel, SpiceMsgIn *in); +static void smartcard_message_free(SpiceSmartcardChannelMessage *message); + +/* ------------------------------------------------------------------ */ +#ifdef USE_SMARTCARD +static void reader_added_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data); +static void reader_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data); +static void card_inserted_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data); +static void card_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data); +#endif + +static void spice_smartcard_channel_init(SpiceSmartcardChannel *channel) +{ + SpiceSmartcardChannelPrivate *priv; + + channel->priv = SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(channel); + priv = channel->priv; + priv->message_queue = g_queue_new(); + +#ifdef USE_SMARTCARD + priv->pending_card_insertions = + g_hash_table_new_full(g_direct_hash, g_direct_equal, + (GDestroyNotify)vreader_free, NULL); + priv->pending_reader_removals = + g_hash_table_new_full(g_direct_hash, g_direct_equal, + (GDestroyNotify)vreader_free, NULL); +#endif +} + +static void spice_smartcard_channel_constructed(GObject *object) +{ + SpiceSession *s = spice_channel_get_session(SPICE_CHANNEL(object)); + + g_return_if_fail(s != NULL); + +#ifdef USE_SMARTCARD + if (!spice_session_is_for_migration(s)) { + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(object); + SpiceSmartcardManager *manager = spice_smartcard_manager_get(); + + spice_g_signal_connect_object(G_OBJECT(manager), "reader-added", + (GCallback)reader_added_cb, channel, 0); + spice_g_signal_connect_object(G_OBJECT(manager), "reader-removed", + (GCallback)reader_removed_cb, channel, 0); + spice_g_signal_connect_object(G_OBJECT(manager), "card-inserted", + (GCallback)card_inserted_cb, channel, 0); + spice_g_signal_connect_object(G_OBJECT(manager), "card-removed", + (GCallback)card_removed_cb, channel, 0); + } +#endif + + if (G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->constructed) + G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->constructed(object); + +} + +static void spice_smartcard_channel_finalize(GObject *obj) +{ + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(obj); + SpiceSmartcardChannelPrivate *c = channel->priv; + + g_clear_pointer(&c->pending_card_insertions, g_hash_table_destroy); + g_clear_pointer(&c->pending_reader_removals, g_hash_table_destroy); + if (c->message_queue != NULL) { + g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL); + g_queue_free(c->message_queue); + c->message_queue = NULL; + } + g_clear_pointer(&c->in_flight_message, smartcard_message_free); + g_clear_pointer(&c->pending_reader_additions, g_list_free); + + if (G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize(obj); +} + +static void spice_smartcard_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceSmartcardChannel *smartcard_channel = SPICE_SMARTCARD_CHANNEL(channel); + SpiceSmartcardChannelPrivate *c = smartcard_channel->priv; + + g_hash_table_remove_all(c->pending_card_insertions); + g_hash_table_remove_all(c->pending_reader_removals); + + if (c->message_queue != NULL) { + g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL); + g_queue_clear(c->message_queue); + } + + g_clear_pointer(&c->in_flight_message, smartcard_message_free); + g_clear_pointer(&c->pending_reader_additions, g_list_free); + + SPICE_CHANNEL_CLASS(spice_smartcard_channel_parent_class)->channel_reset(channel, migrating); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_SMARTCARD_DATA ] = handle_smartcard_msg, + }; + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->finalize = spice_smartcard_channel_finalize; + gobject_class->constructed = spice_smartcard_channel_constructed; + + channel_class->channel_up = spice_smartcard_channel_up; + channel_class->channel_reset = spice_smartcard_channel_reset; + + g_type_class_add_private(klass, sizeof(SpiceSmartcardChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +} + +/* ------------------------------------------------------------------ */ +/* private api */ + +static void +smartcard_message_free(SpiceSmartcardChannelMessage *message) +{ + if (message->message) + spice_msg_out_unref(message->message); + g_free(message); +} + +#ifdef USE_SMARTCARD +static gboolean is_attached_to_server(VReader *reader) +{ + return (vreader_get_id(reader) != (vreader_id_t)-1); +} + +static gboolean +spice_channel_has_pending_card_insertion(SpiceSmartcardChannel *channel, + VReader *reader) +{ + return (g_hash_table_lookup(channel->priv->pending_card_insertions, reader) != NULL); +} + +static void +spice_channel_queue_card_insertion(SpiceSmartcardChannel *channel, + VReader *reader) +{ + vreader_reference(reader); + g_hash_table_insert(channel->priv->pending_card_insertions, + reader, reader); +} + +static void +spice_channel_drop_pending_card_insertion(SpiceSmartcardChannel *channel, + VReader *reader) +{ + g_hash_table_remove(channel->priv->pending_card_insertions, reader); +} + +static gboolean +spice_channel_has_pending_reader_removal(SpiceSmartcardChannel *channel, + VReader *reader) +{ + return (g_hash_table_lookup(channel->priv->pending_reader_removals, reader) != NULL); +} + +static void +spice_channel_queue_reader_removal(SpiceSmartcardChannel *channel, + VReader *reader) +{ + vreader_reference(reader); + g_hash_table_insert(channel->priv->pending_reader_removals, + reader, reader); +} + +static void +spice_channel_drop_pending_reader_removal(SpiceSmartcardChannel *channel, + VReader *reader) +{ + g_hash_table_remove(channel->priv->pending_reader_removals, reader); +} + +static SpiceSmartcardChannelMessage * +smartcard_message_new(VSCMsgType msg_type, SpiceMsgOut *msg_out) +{ + SpiceSmartcardChannelMessage *message; + + message = g_new0(SpiceSmartcardChannelMessage, 1); + message->message = msg_out; + message->message_type = msg_type; + + return message; +} + +/* Indicates that handling of the message that is currently in flight has + * been completed. If needed, sends the next queued command to the server. */ +static void +smartcard_message_complete_in_flight(SpiceSmartcardChannel *channel) +{ + g_return_if_fail(channel->priv->in_flight_message != NULL); + + smartcard_message_free(channel->priv->in_flight_message); + channel->priv->in_flight_message = g_queue_pop_head(channel->priv->message_queue); + if (channel->priv->in_flight_message != NULL) { + spice_msg_out_send(channel->priv->in_flight_message->message); + channel->priv->in_flight_message->message = NULL; + } +} + +static void smartcard_message_send(SpiceSmartcardChannel *channel, + VSCMsgType msg_type, + SpiceMsgOut *msg_out, gboolean queue) +{ + SpiceSmartcardChannelMessage *message; + + if (spice_channel_get_read_only(SPICE_CHANNEL(channel))) + return; + + CHANNEL_DEBUG(channel, "send message %u, %s", + msg_type, queue ? "queued" : "now"); + if (!queue) { + spice_msg_out_send(msg_out); + return; + } + + message = smartcard_message_new(msg_type, msg_out); + if (channel->priv->in_flight_message == NULL) { + g_return_if_fail(g_queue_is_empty(channel->priv->message_queue)); + channel->priv->in_flight_message = message; + spice_msg_out_send(channel->priv->in_flight_message->message); + channel->priv->in_flight_message->message = NULL; + } else { + g_queue_push_tail(channel->priv->message_queue, message); + } +} + +static void +send_msg_generic_with_data(SpiceSmartcardChannel *channel, VReader *reader, + VSCMsgType msg_type, + const uint8_t *data, gsize data_len, + gboolean serialize_msg) +{ + SpiceMsgOut *msg_out; + VSCMsgHeader header = { + .type = msg_type, + .length = data_len + }; + + if(vreader_get_id(reader) == -1) + header.reader_id = VSCARD_UNDEFINED_READER_ID; + else + header.reader_id = vreader_get_id(reader); + + msg_out = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_SMARTCARD_DATA); + msg_out->marshallers->msgc_smartcard_header(msg_out->marshaller, &header); + if ((data != NULL) && (data_len != 0)) { + spice_marshaller_add(msg_out->marshaller, data, data_len); + } + + smartcard_message_send(channel, msg_type, msg_out, serialize_msg); +} + +static void send_msg_generic(SpiceSmartcardChannel *channel, VReader *reader, + VSCMsgType msg_type) +{ + send_msg_generic_with_data(channel, reader, msg_type, NULL, 0, TRUE); +} + +static void send_msg_atr(SpiceSmartcardChannel *channel, VReader *reader) +{ +#define MAX_ATR_LEN 40 //this should be defined in libcacard + uint8_t atr[MAX_ATR_LEN]; + int atr_len = MAX_ATR_LEN; + + g_return_if_fail(vreader_get_id(reader) != VSCARD_UNDEFINED_READER_ID); + vreader_power_on(reader, atr, &atr_len); + send_msg_generic_with_data(channel, reader, VSC_ATR, atr, atr_len, TRUE); +} + +static void reader_added_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(user_data); + const char *reader_name = vreader_get_name(reader); + + if (vreader_get_id(reader) != -1 || + g_list_find(channel->priv->pending_reader_additions, reader)) + return; + + channel->priv->pending_reader_additions = + g_list_append(channel->priv->pending_reader_additions, reader); + + send_msg_generic_with_data(channel, reader, VSC_ReaderAdd, + (uint8_t*)reader_name, strlen(reader_name), TRUE); +} + +static void reader_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(user_data); + + if (is_attached_to_server(reader)) { + send_msg_generic(channel, reader, VSC_ReaderRemove); + } else { + spice_channel_queue_reader_removal(channel, reader); + } +} + +/* ------------------------------------------------------------------ */ +/* callbacks */ +static void card_inserted_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(user_data); + + if (is_attached_to_server(reader)) { + send_msg_atr(channel, reader); + } else { + spice_channel_queue_card_insertion(channel, reader); + } +} + +static void card_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(user_data); + + if (is_attached_to_server(reader)) { + send_msg_generic(channel, reader, VSC_CardRemove); + } else { + /* this does nothing when reader has no card insertion pending */ + spice_channel_drop_pending_card_insertion(channel, reader); + } +} +#endif /* USE_SMARTCARD */ + +static void spice_smartcard_channel_up_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceChannel *channel = SPICE_CHANNEL(user_data); +#ifdef USE_SMARTCARD + SpiceSmartcardManager *manager = spice_smartcard_manager_get(); + GList *l, *list = NULL; +#endif + GError *error = NULL; + + g_return_if_fail(channel != NULL); + g_return_if_fail(SPICE_IS_SESSION(source_object)); + + spice_smartcard_manager_init_finish(SPICE_SESSION(source_object), + res, &error); + if (error) { + g_warning("%s", error->message); + goto end; + } + +#ifdef USE_SMARTCARD + list = spice_smartcard_manager_get_readers(manager); + for (l = list; l != NULL; l = l->next) { + VReader *reader = l->data; + gboolean has_card = vreader_card_is_present(reader) == VREADER_OK; + + reader_added_cb(manager, reader, channel); + if (has_card) + card_inserted_cb(manager, reader, channel); + + g_boxed_free(SPICE_TYPE_SMARTCARD_READER, reader); + } +#endif + +end: +#ifdef USE_SMARTCARD + g_list_free(list); +#endif + g_clear_error(&error); +} + +static void spice_smartcard_channel_up(SpiceChannel *channel) +{ + if (spice_session_is_for_migration(spice_channel_get_session(channel))) + return; + + spice_smartcard_manager_init_async(spice_channel_get_session(channel), + g_cancellable_new(), + spice_smartcard_channel_up_cb, + channel); +} + +static void handle_smartcard_msg(SpiceChannel *channel, SpiceMsgIn *in) +{ +#ifdef USE_SMARTCARD + SpiceSmartcardChannel *smartcard_channel = SPICE_SMARTCARD_CHANNEL(channel); + SpiceSmartcardChannelPrivate *priv = smartcard_channel->priv; + SpiceMsgSmartcard *msg = spice_msg_in_parsed(in); + VReader *reader; + + CHANNEL_DEBUG(channel, "handle msg %u", msg->type); + switch (msg->type) { + case VSC_Error: + g_return_if_fail(priv->in_flight_message != NULL); + CHANNEL_DEBUG(channel, "in flight %u", priv->in_flight_message->message_type); + switch (priv->in_flight_message->message_type) { + case VSC_ReaderAdd: + g_return_if_fail(priv->pending_reader_additions != NULL); + reader = priv->pending_reader_additions->data; + g_return_if_fail(reader != NULL); + g_return_if_fail(vreader_get_id(reader) == -1); + priv->pending_reader_additions = + g_list_delete_link(priv->pending_reader_additions, + priv->pending_reader_additions); + vreader_set_id(reader, msg->reader_id); + + if (spice_channel_has_pending_card_insertion(smartcard_channel, reader)) { + send_msg_atr(smartcard_channel, reader); + spice_channel_drop_pending_card_insertion(smartcard_channel, reader); + } + + if (spice_channel_has_pending_reader_removal(smartcard_channel, reader)) { + send_msg_generic(smartcard_channel, reader, VSC_CardRemove); + spice_channel_drop_pending_reader_removal(smartcard_channel, reader); + } + break; + case VSC_APDU: + case VSC_ATR: + case VSC_CardRemove: + case VSC_Error: + case VSC_ReaderRemove: + break; + default: + g_warning("Unexpected message: %u", priv->in_flight_message->message_type); + break; + } + smartcard_message_complete_in_flight(smartcard_channel); + + break; + + case VSC_APDU: + case VSC_Init: { + const unsigned int APDU_BUFFER_SIZE = 270; + VReaderStatus reader_status; + uint8_t data_out[APDU_BUFFER_SIZE + sizeof(uint32_t)]; + int data_out_len = sizeof(data_out); + + g_return_if_fail(msg->reader_id != VSCARD_UNDEFINED_READER_ID); + reader = vreader_get_reader_by_id(msg->reader_id); + g_return_if_fail(reader != NULL); //FIXME: add log message + + reader_status = vreader_xfr_bytes(reader, + msg->data, msg->length, + data_out, &data_out_len); + if (reader_status == VREADER_OK) { + send_msg_generic_with_data(smartcard_channel, + reader, VSC_APDU, + data_out, data_out_len, FALSE); + } else { + uint32_t error_code; + error_code = GUINT32_TO_LE(reader_status); + send_msg_generic_with_data(smartcard_channel, + reader, VSC_Error, + (uint8_t*)&error_code, + sizeof (error_code), FALSE); + } + break; + } + default: + g_return_if_reached(); + } +#endif +} diff --git a/src/channel-smartcard.h b/src/channel-smartcard.h new file mode 100644 index 0000000..10926d0 --- /dev/null +++ b/src/channel-smartcard.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_SMARTCARD_CHANNEL_H__ +#define __SPICE_CLIENT_SMARTCARD_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_SMARTCARD_CHANNEL (spice_smartcard_channel_get_type()) +#define SPICE_SMARTCARD_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_SMARTCARD_CHANNEL, SpiceSmartcardChannel)) +#define SPICE_SMARTCARD_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_SMARTCARD_CHANNEL, SpiceSmartcardChannelClass)) +#define SPICE_IS_SMARTCARD_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_SMARTCARD_CHANNEL)) +#define SPICE_IS_SMARTCARD_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_SMARTCARD_CHANNEL)) +#define SPICE_SMARTCARD_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_SMARTCARD_CHANNEL, SpiceSmartcardChannelClass)) + +typedef struct _SpiceSmartcardChannel SpiceSmartcardChannel; +typedef struct _SpiceSmartcardChannelClass SpiceSmartcardChannelClass; +typedef struct _SpiceSmartcardChannelPrivate SpiceSmartcardChannelPrivate; + +/** + * SpiceSmartcardChannel: + * + * The #SpiceSmartcardChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceSmartcardChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceSmartcardChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceSmartcardChannelClass: + * @parent_class: Parent class. + * + * Class structure for #SpiceSmartcardChannel. + */ +struct _SpiceSmartcardChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_smartcard_channel_get_type(void); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_SMARTCARD_CHANNEL_H__ */ diff --git a/src/channel-usbredir-priv.h b/src/channel-usbredir-priv.h new file mode 100644 index 0000000..17e9716 --- /dev/null +++ b/src/channel-usbredir-priv.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_USBREDIR_CHANNEL_PRIV_H__ +#define __SPICE_CLIENT_USBREDIR_CHANNEL_PRIV_H__ + +#include +#include +#include "spice-client.h" + +G_BEGIN_DECLS + +/* Note: this must be called before calling any other functions, and the + context should not be destroyed before the last device has been + disconnected */ +void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel, + libusb_context *context); + +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel *channel, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean spice_usbredir_channel_disconnect_device_finish(SpiceUsbredirChannel *channel, + GAsyncResult *res, + GError **err); + +/* Note the context must be set, and the channel must be brought up + (through spice_channel_connect()), before calling this. */ +void spice_usbredir_channel_connect_device_async( + SpiceUsbredirChannel *channel, + libusb_device *device, + SpiceUsbDevice *spice_device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean spice_usbredir_channel_connect_device_finish( + SpiceUsbredirChannel *channel, + GAsyncResult *res, + GError **err); + +void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel); + +libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel); + +void spice_usbredir_channel_lock(SpiceUsbredirChannel *channel); + +void spice_usbredir_channel_unlock(SpiceUsbredirChannel *channel); + +void spice_usbredir_channel_get_guest_filter( + SpiceUsbredirChannel *channel, + const struct usbredirfilter_rule **rules_ret, + int *rules_count_ret); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_USBREDIR_CHANNEL_PRIV_H__ */ diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c new file mode 100644 index 0000000..2c5feae --- /dev/null +++ b/src/channel-usbredir.c @@ -0,0 +1,796 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede + Richard Hughes + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#ifdef USE_USBREDIR +#include +#include +#ifdef USE_POLKIT +#include "usb-acl-helper.h" +#endif +#include "channel-usbredir-priv.h" +#include "usb-device-manager-priv.h" +#include "usbutil.h" +#endif + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-channel-priv.h" + +/** + * SECTION:channel-usbredir + * @short_description: usb redirection + * @title: USB Redirection Channel + * @section_id: + * @stability: Stable + * @include: spice-client.h + * + * The Spice protocol defines a set of messages to redirect USB devices + * from the Spice client to the VM. This channel handles these messages. + */ + +#ifdef USE_USBREDIR + +#define SPICE_USBREDIR_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_USBREDIR_CHANNEL, SpiceUsbredirChannelPrivate)) + +enum SpiceUsbredirChannelState { + STATE_DISCONNECTED, +#ifdef USE_POLKIT + STATE_WAITING_FOR_ACL_HELPER, +#endif + STATE_CONNECTED, + STATE_DISCONNECTING, +}; + +struct _SpiceUsbredirChannelPrivate { + libusb_device *device; + SpiceUsbDevice *spice_device; + libusb_context *context; + struct usbredirhost *host; + /* To catch usbredirhost error messages and report them as a GError */ + GError **catch_error; + /* Data passed from channel handle msg to the usbredirhost read cb */ + const uint8_t *read_buf; + int read_buf_size; + enum SpiceUsbredirChannelState state; +#ifdef USE_POLKIT + GTask *task; + SpiceUsbAclHelper *acl_helper; +#endif + GMutex device_connect_mutex; +}; + +static void channel_set_handlers(SpiceChannelClass *klass); +static void spice_usbredir_channel_up(SpiceChannel *channel); +static void spice_usbredir_channel_dispose(GObject *obj); +static void spice_usbredir_channel_finalize(GObject *obj); +static void usbredir_handle_msg(SpiceChannel *channel, SpiceMsgIn *in); + +static void usbredir_log(void *user_data, int level, const char *msg); +static int usbredir_read_callback(void *user_data, uint8_t *data, int count); +static int usbredir_write_callback(void *user_data, uint8_t *data, int count); +static void usbredir_write_flush_callback(void *user_data); +#if USBREDIR_VERSION >= 0x000701 +static uint64_t usbredir_buffered_output_size_callback(void *user_data); +#endif + +static void *usbredir_alloc_lock(void); +static void usbredir_lock_lock(void *user_data); +static void usbredir_unlock_lock(void *user_data); +static void usbredir_free_lock(void *user_data); + +#endif + +G_DEFINE_TYPE(SpiceUsbredirChannel, spice_usbredir_channel, SPICE_TYPE_CHANNEL) + +/* ------------------------------------------------------------------ */ + +static void spice_usbredir_channel_init(SpiceUsbredirChannel *channel) +{ +#ifdef USE_USBREDIR + channel->priv = SPICE_USBREDIR_CHANNEL_GET_PRIVATE(channel); + g_mutex_init(&channel->priv->device_connect_mutex); +#endif +} + +#ifdef USE_USBREDIR + +static void _channel_reset_finish(SpiceUsbredirChannel *channel) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + + spice_usbredir_channel_lock(channel); + + usbredirhost_close(priv->host); + priv->host = NULL; + + /* Call set_context to re-create the host */ + spice_usbredir_channel_set_context(channel, priv->context); + + spice_usbredir_channel_unlock(channel); +} + +static void _channel_reset_cb(GObject *gobject, + GAsyncResult *result, + gpointer user_data) +{ + SpiceChannel *spice_channel = SPICE_CHANNEL(gobject); + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(spice_channel); + gboolean migrating = GPOINTER_TO_UINT(user_data); + GError *err = NULL; + + _channel_reset_finish(channel); + + SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(spice_channel, migrating); + + spice_usbredir_channel_disconnect_device_finish(channel, result, &err); + g_object_unref(result); +} + +static void spice_usbredir_channel_reset(SpiceChannel *c, gboolean migrating) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c); + SpiceUsbredirChannelPrivate *priv = channel->priv; + + if (priv->host) { + if (priv->state == STATE_CONNECTED) { + spice_usbredir_channel_disconnect_device_async(channel, NULL, + _channel_reset_cb, GUINT_TO_POINTER(migrating)); + } else { + _channel_reset_finish(channel); + } + } else { + SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(c, migrating); + } +} +#endif + +static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass) +{ +#ifdef USE_USBREDIR + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->dispose = spice_usbredir_channel_dispose; + gobject_class->finalize = spice_usbredir_channel_finalize; + channel_class->channel_up = spice_usbredir_channel_up; + channel_class->channel_reset = spice_usbredir_channel_reset; + + g_type_class_add_private(klass, sizeof(SpiceUsbredirChannelPrivate)); + channel_set_handlers(SPICE_CHANNEL_CLASS(klass)); +#endif +} + +#ifdef USE_USBREDIR +static void spice_usbredir_channel_dispose(GObject *obj) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(obj); + + spice_usbredir_channel_disconnect_device(channel); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->dispose) + G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->dispose(obj); +} + +/* + * Note we don't unref our device / acl_helper / result references in our + * finalize. The reason for this is that depending on our state at dispose + * time they are either: + * 1) Already unreferenced + * 2) Will be unreferenced by the disconnect_device call from dispose + * 3) Will be unreferenced by spice_usbredir_channel_open_acl_cb + * + * Now the last one may seem like an issue, since what will happen if + * spice_usbredir_channel_open_acl_cb will run after finalization? + * + * This will never happens since the GSimpleAsyncResult created before we + * get into the STATE_WAITING_FOR_ACL_HELPER takes a reference to its + * source object, which is our SpiceUsbredirChannel object, so + * the finalize won't hapen until spice_usbredir_channel_open_acl_cb runs, + * and unrefs priv->result which will in turn unref ourselve once the + * complete_in_idle call it does has completed. And once + * spice_usbredir_channel_open_acl_cb has run, all references we hold have + * been released even in the 3th scenario. + */ +static void spice_usbredir_channel_finalize(GObject *obj) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(obj); + + if (channel->priv->host) + usbredirhost_close(channel->priv->host); +#ifdef USE_USBREDIR + g_mutex_clear(&channel->priv->device_connect_mutex); +#endif + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->finalize(obj); +} + +static void channel_set_handlers(SpiceChannelClass *klass) +{ + static const spice_msg_handler handlers[] = { + [ SPICE_MSG_SPICEVMC_DATA ] = usbredir_handle_msg, + }; + + spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers)); +} + +/* ------------------------------------------------------------------ */ +/* private api */ + +G_GNUC_INTERNAL +void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel, + libusb_context *context) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + + g_return_if_fail(priv->host == NULL); + + priv->context = context; + priv->host = usbredirhost_open_full( + context, NULL, + usbredir_log, + usbredir_read_callback, + usbredir_write_callback, + usbredir_write_flush_callback, + usbredir_alloc_lock, + usbredir_lock_lock, + usbredir_unlock_lock, + usbredir_free_lock, + channel, PACKAGE_STRING, + spice_util_get_debug() ? usbredirparser_debug : usbredirparser_warning, + usbredirhost_fl_write_cb_owns_buffer); + if (!priv->host) + g_error("Out of memory allocating usbredirhost"); + +#if USBREDIR_VERSION >= 0x000701 + usbredirhost_set_buffered_output_size_cb(priv->host, usbredir_buffered_output_size_callback); +#endif +} + +static gboolean spice_usbredir_channel_open_device( + SpiceUsbredirChannel *channel, GError **err) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + libusb_device_handle *handle = NULL; + int rc, status; + + g_return_val_if_fail(priv->state == STATE_DISCONNECTED +#ifdef USE_POLKIT + || priv->state == STATE_WAITING_FOR_ACL_HELPER +#endif + , FALSE); + + rc = libusb_open(priv->device, &handle); + if (rc != 0) { + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Could not open usb device: %s [%i]", + spice_usbutil_libusb_strerror(rc), rc); + return FALSE; + } + + priv->catch_error = err; + status = usbredirhost_set_device(priv->host, handle); + priv->catch_error = NULL; + if (status != usb_redir_success) { + g_return_val_if_fail(err == NULL || *err != NULL, FALSE); + return FALSE; + } + + if (!spice_usb_device_manager_start_event_listening( + spice_usb_device_manager_get( + spice_channel_get_session(SPICE_CHANNEL(channel)), NULL), + err)) { + usbredirhost_set_device(priv->host, NULL); + return FALSE; + } + + priv->state = STATE_CONNECTED; + + return TRUE; +} + +#ifdef USE_POLKIT +static void spice_usbredir_channel_open_acl_cb( + GObject *gobject, GAsyncResult *acl_res, gpointer user_data) +{ + SpiceUsbAclHelper *acl_helper = SPICE_USB_ACL_HELPER(gobject); + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(user_data); + SpiceUsbredirChannelPrivate *priv = channel->priv; + GError *err = NULL; + + g_return_if_fail(acl_helper == priv->acl_helper); + g_return_if_fail(priv->state == STATE_WAITING_FOR_ACL_HELPER || + priv->state == STATE_DISCONNECTING); + + spice_usb_acl_helper_open_acl_finish(acl_helper, acl_res, &err); + if (!err && priv->state == STATE_DISCONNECTING) { + err = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_CANCELLED, + "USB redirection channel connect cancelled"); + } + if (!err) { + spice_usbredir_channel_open_device(channel, &err); + } + if (err) { + g_clear_pointer(&priv->device, libusb_unref_device); + g_boxed_free(spice_usb_device_get_type(), priv->spice_device); + priv->spice_device = NULL; + priv->state = STATE_DISCONNECTED; + g_task_return_error(priv->task, err); + } else { + g_task_return_boolean(priv->task, TRUE); + } + + g_clear_object(&priv->acl_helper); + g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)), + "inhibit-keyboard-grab", FALSE, NULL); + + g_clear_object(&priv->task); +} +#endif + +#ifndef USE_POLKIT +static void +_open_device_async_cb(GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) +{ + GError *err = NULL; + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object); + SpiceUsbredirChannelPrivate *priv = channel->priv; + + spice_usbredir_channel_lock(channel); + + if (!spice_usbredir_channel_open_device(channel, &err)) { + g_clear_pointer(&priv->device, libusb_unref_device); + g_boxed_free(spice_usb_device_get_type(), priv->spice_device); + priv->spice_device = NULL; + } + + spice_usbredir_channel_unlock(channel); + + if (err) { + g_task_return_error(task, err); + } else { + g_task_return_boolean(task, TRUE); + } +} +#endif + +G_GNUC_INTERNAL +void spice_usbredir_channel_connect_device_async( + SpiceUsbredirChannel *channel, + libusb_device *device, + SpiceUsbDevice *spice_device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + GTask *task; + + g_return_if_fail(SPICE_IS_USBREDIR_CHANNEL(channel)); + g_return_if_fail(device != NULL); + + CHANNEL_DEBUG(channel, "connecting device %04x:%04x (%p) to channel %p", + spice_usb_device_get_vid(spice_device), + spice_usb_device_get_pid(spice_device), + spice_device, channel); + + task = g_task_new(channel, cancellable, callback, user_data); + + if (!priv->host) { + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error libusb context not set"); + goto done; + } + + if (priv->state != STATE_DISCONNECTED) { + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error channel is busy"); + goto done; + } + + priv->device = libusb_ref_device(device); + priv->spice_device = g_boxed_copy(spice_usb_device_get_type(), + spice_device); +#ifdef USE_POLKIT + priv->task = task; + priv->state = STATE_WAITING_FOR_ACL_HELPER; + priv->acl_helper = spice_usb_acl_helper_new(); + g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)), + "inhibit-keyboard-grab", TRUE, NULL); + spice_usb_acl_helper_open_acl_async(priv->acl_helper, + libusb_get_bus_number(device), + libusb_get_device_address(device), + cancellable, + spice_usbredir_channel_open_acl_cb, + channel); + return; +#else + g_task_run_in_thread(task, _open_device_async_cb); +#endif + +done: + g_object_unref(task); +} + +G_GNUC_INTERNAL +gboolean spice_usbredir_channel_connect_device_finish( + SpiceUsbredirChannel *channel, + GAsyncResult *res, + GError **err) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, channel), FALSE); + + return g_task_propagate_boolean(task, err); +} + +G_GNUC_INTERNAL +void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + + CHANNEL_DEBUG(channel, "disconnecting device from usb channel %p", channel); + + spice_usbredir_channel_lock(channel); + + switch (priv->state) { + case STATE_DISCONNECTED: + case STATE_DISCONNECTING: + break; +#ifdef USE_POLKIT + case STATE_WAITING_FOR_ACL_HELPER: + priv->state = STATE_DISCONNECTING; + /* We're still waiting for the acl helper -> cancel it */ + spice_usb_acl_helper_cancel(priv->acl_helper); + break; +#endif + case STATE_CONNECTED: + /* + * This sets the usb event thread run condition to FALSE, therefor + * it must be done before usbredirhost_set_device NULL, as + * usbredirhost_set_device NULL will interrupt the + * libusb_handle_events call in the thread. + */ + { + SpiceSession *session = spice_channel_get_session(SPICE_CHANNEL(channel)); + if (session != NULL) + spice_usb_device_manager_stop_event_listening( + spice_usb_device_manager_get(session, NULL)); + } + /* This also closes the libusb handle we passed from open_device */ + usbredirhost_set_device(priv->host, NULL); + g_clear_pointer(&priv->device, libusb_unref_device); + g_boxed_free(spice_usb_device_get_type(), priv->spice_device); + priv->spice_device = NULL; + priv->state = STATE_DISCONNECTED; + break; + } + + spice_usbredir_channel_unlock(channel); +} + +static void +_disconnect_device_thread(GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) +{ + spice_usbredir_channel_disconnect_device(SPICE_USBREDIR_CHANNEL(object)); + g_task_return_boolean(task, TRUE); +} + +G_GNUC_INTERNAL +gboolean spice_usbredir_channel_disconnect_device_finish( + SpiceUsbredirChannel *channel, + GAsyncResult *res, + GError **err) +{ + return g_task_propagate_boolean(G_TASK(res), err); +} + +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel *channel, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask* task = g_task_new(channel, cancellable, callback, user_data); + + g_return_if_fail(channel != NULL); + g_task_run_in_thread(task, _disconnect_device_thread); +} + +G_GNUC_INTERNAL +libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel) +{ + return channel->priv->device; +} + +G_GNUC_INTERNAL +void spice_usbredir_channel_get_guest_filter( + SpiceUsbredirChannel *channel, + const struct usbredirfilter_rule **rules_ret, + int *rules_count_ret) +{ + SpiceUsbredirChannelPrivate *priv = channel->priv; + + g_return_if_fail(priv->host != NULL); + + usbredirhost_get_guest_filter(priv->host, rules_ret, rules_count_ret); +} + +/* ------------------------------------------------------------------ */ +/* callbacks (any context) */ + +#if USBREDIR_VERSION >= 0x000701 +static uint64_t usbredir_buffered_output_size_callback(void *user_data) +{ + g_return_val_if_fail(SPICE_IS_USBREDIR_CHANNEL(user_data), 0); + return spice_channel_get_queue_size(SPICE_CHANNEL(user_data)); +} +#endif + +/* Note that this function must be re-entrant safe, as it can get called + from both the main thread as well as from the usb event handling thread */ +static void usbredir_write_flush_callback(void *user_data) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(user_data); + SpiceUsbredirChannelPrivate *priv = channel->priv; + + if (spice_channel_get_state(SPICE_CHANNEL(channel)) != + SPICE_CHANNEL_STATE_READY) + return; + + if (!priv->host) + return; + + usbredirhost_write_guest_data(priv->host); +} + +static void usbredir_log(void *user_data, int level, const char *msg) +{ + SpiceUsbredirChannel *channel = user_data; + SpiceUsbredirChannelPrivate *priv = channel->priv; + + if (priv->catch_error && level == usbredirparser_error) { + CHANNEL_DEBUG(channel, "%s", msg); + /* Remove "usbredirhost: " prefix from usbredirhost messages */ + if (strncmp(msg, "usbredirhost: ", 14) == 0) + g_set_error_literal(priv->catch_error, SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, msg + 14); + else + g_set_error_literal(priv->catch_error, SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, msg); + return; + } + + switch (level) { + case usbredirparser_error: + g_critical("%s", msg); break; + case usbredirparser_warning: + g_warning("%s", msg); break; + default: + CHANNEL_DEBUG(channel, "%s", msg); break; + } +} + +static int usbredir_read_callback(void *user_data, uint8_t *data, int count) +{ + SpiceUsbredirChannel *channel = user_data; + SpiceUsbredirChannelPrivate *priv = channel->priv; + + if (priv->read_buf_size < count) { + count = priv->read_buf_size; + } + + memcpy(data, priv->read_buf, count); + + priv->read_buf_size -= count; + if (priv->read_buf_size) { + priv->read_buf += count; + } else { + priv->read_buf = NULL; + } + + return count; +} + +static void usbredir_free_write_cb_data(uint8_t *data, void *user_data) +{ + SpiceUsbredirChannel *channel = user_data; + SpiceUsbredirChannelPrivate *priv = channel->priv; + + usbredirhost_free_write_buffer(priv->host, data); +} + +static int usbredir_write_callback(void *user_data, uint8_t *data, int count) +{ + SpiceUsbredirChannel *channel = user_data; + SpiceMsgOut *msg_out; + + msg_out = spice_msg_out_new(SPICE_CHANNEL(channel), + SPICE_MSGC_SPICEVMC_DATA); + spice_marshaller_add_ref_full(msg_out->marshaller, data, count, + usbredir_free_write_cb_data, channel); + spice_msg_out_send(msg_out); + + return count; +} + +static void *usbredir_alloc_lock(void) { + GMutex *mutex; + + mutex = g_new0(GMutex, 1); + g_mutex_init(mutex); + + return mutex; +} + +void spice_usbredir_channel_lock(SpiceUsbredirChannel *channel) +{ + g_mutex_lock(&channel->priv->device_connect_mutex); +} + +void spice_usbredir_channel_unlock(SpiceUsbredirChannel *channel) +{ + g_mutex_unlock(&channel->priv->device_connect_mutex); +} + +static void usbredir_lock_lock(void *user_data) { + GMutex *mutex = user_data; + + g_mutex_lock(mutex); +} + +static void usbredir_unlock_lock(void *user_data) { + GMutex *mutex = user_data; + + g_mutex_unlock(mutex); +} + +static void usbredir_free_lock(void *user_data) { + GMutex *mutex = user_data; + + g_mutex_clear(mutex); + g_free(mutex); +} + +/* --------------------------------------------------------------------- */ + +typedef struct device_error_data { + SpiceUsbredirChannel *channel; + SpiceUsbDevice *spice_device; + GError *error; + struct coroutine *caller; +} device_error_data; + +/* main context */ +static gboolean device_error(gpointer user_data) +{ + device_error_data *data = user_data; + SpiceUsbredirChannel *channel = data->channel; + SpiceUsbredirChannelPrivate *priv = channel->priv; + + /* Check that the device has not changed before we manage to run */ + if (data->spice_device == priv->spice_device) { + spice_usbredir_channel_disconnect_device(channel); + spice_usb_device_manager_device_error( + spice_usb_device_manager_get( + spice_channel_get_session(SPICE_CHANNEL(channel)), NULL), + data->spice_device, data->error); + } + + coroutine_yieldto(data->caller, NULL); + return FALSE; +} + +/* --------------------------------------------------------------------- */ +/* coroutine context */ +static void spice_usbredir_channel_up(SpiceChannel *c) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c); + SpiceUsbredirChannelPrivate *priv = channel->priv; + + /* Flush any pending writes */ + usbredirhost_write_guest_data(priv->host); +} + +static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c); + SpiceUsbredirChannelPrivate *priv = channel->priv; + int r, size; + uint8_t *buf; + + g_return_if_fail(priv->host != NULL); + + /* No recursion allowed! */ + g_return_if_fail(priv->read_buf == NULL); + + buf = spice_msg_in_raw(in, &size); + priv->read_buf = buf; + priv->read_buf_size = size; + + spice_usbredir_channel_lock(channel); + + r = usbredirhost_read_guest_data(priv->host); + if (r != 0) { + SpiceUsbDevice *spice_device = priv->spice_device; + device_error_data err_data; + gchar *desc; + GError *err; + + if (spice_device == NULL) { + spice_usbredir_channel_unlock(channel); + return; + } + + desc = spice_usb_device_get_description(spice_device, NULL); + switch (r) { + case usbredirhost_read_parse_error: + err = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("usbredir protocol parse error for %s"), desc); + break; + case usbredirhost_read_device_rejected: + err = g_error_new(SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_USB_DEVICE_REJECTED, + _("%s rejected by host"), desc); + break; + case usbredirhost_read_device_lost: + err = g_error_new(SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_USB_DEVICE_LOST, + _("%s disconnected (fatal IO error)"), desc); + break; + default: + err = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("Unknown error (%d) for %s"), r, desc); + } + g_free(desc); + + CHANNEL_DEBUG(c, "%s", err->message); + + err_data.channel = channel; + err_data.caller = coroutine_self(); + err_data.spice_device = g_boxed_copy(spice_usb_device_get_type(), spice_device); + err_data.error = err; + g_idle_add(device_error, &err_data); + coroutine_yield(NULL); + + g_boxed_free(spice_usb_device_get_type(), err_data.spice_device); + + g_error_free(err); + } + + spice_usbredir_channel_unlock(channel); +} + +#endif /* USE_USBREDIR */ diff --git a/src/channel-usbredir.h b/src/channel-usbredir.h new file mode 100644 index 0000000..0b43060 --- /dev/null +++ b/src/channel-usbredir.h @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_USBREDIR_CHANNEL_H__ +#define __SPICE_CLIENT_USBREDIR_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_USBREDIR_CHANNEL (spice_usbredir_channel_get_type()) +#define SPICE_USBREDIR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_USBREDIR_CHANNEL, SpiceUsbredirChannel)) +#define SPICE_USBREDIR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_USBREDIR_CHANNEL, SpiceUsbredirChannelClass)) +#define SPICE_IS_USBREDIR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_USBREDIR_CHANNEL)) +#define SPICE_IS_USBREDIR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_USBREDIR_CHANNEL)) +#define SPICE_USBREDIR_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_USBREDIR_CHANNEL, SpiceUsbredirChannelClass)) + +typedef struct _SpiceUsbredirChannel SpiceUsbredirChannel; +typedef struct _SpiceUsbredirChannelClass SpiceUsbredirChannelClass; +typedef struct _SpiceUsbredirChannelPrivate SpiceUsbredirChannelPrivate; + +/** + * SpiceUsbredirChannel: + * + * The #SpiceUsbredirChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceUsbredirChannel { + SpiceChannel parent; + + /*< private >*/ + SpiceUsbredirChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceUsbredirChannelClass: + * @parent_class: Parent class. + * + * Class structure for #SpiceUsbredirChannel. + */ +struct _SpiceUsbredirChannelClass { + SpiceChannelClass parent_class; + + /* signals */ + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_usbredir_channel_get_type(void); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_USBREDIR_CHANNEL_H__ */ diff --git a/src/channel-webdav.c b/src/channel-webdav.c new file mode 100644 index 0000000..307a867 --- /dev/null +++ b/src/channel-webdav.c @@ -0,0 +1,616 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" +#include "spice-session-priv.h" +#include "spice-marshal.h" +#include "vmcstream.h" +#include "giopipe.h" + +/** + * SECTION:channel-webdav + * @short_description: exports a directory + * @title: WebDAV Channel + * @section_id: + * @see_also: #SpiceChannel + * @stability: Stable + * @include: spice-client.h + * + * The "webdav" channel exports a directory to the guest for file + * manipulation (read/write/copy etc). The underlying protocol is + * implemented using WebDAV (RFC 4918). + * + * By default, the shared directory is the one associated with GLib + * %G_USER_DIRECTORY_PUBLIC_SHARE. You can specify a different + * directory with #SpiceSession #SpiceSession:shared-dir property. + * + * Since: 0.24 + */ + +#define SPICE_WEBDAV_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_WEBDAV_CHANNEL, SpiceWebdavChannelPrivate)) + +typedef struct _OutputQueue OutputQueue; + +struct _SpiceWebdavChannelPrivate { + SpiceVmcStream *stream; + GCancellable *cancellable; + GHashTable *clients; + OutputQueue *queue; + + gboolean demuxing; + struct _demux { + gint64 client; + guint16 size; + guint8 *buf; + } demux; +}; + +G_DEFINE_TYPE(SpiceWebdavChannel, spice_webdav_channel, SPICE_TYPE_PORT_CHANNEL) + +static void spice_webdav_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg); + +struct _OutputQueue { + GOutputStream *output; + gboolean flushing; + guint idle_id; + GQueue *queue; +}; + +typedef struct _OutputQueueElem { + OutputQueue *queue; + const guint8 *buf; + gsize size; + GFunc pushed_cb; + gpointer user_data; +} OutputQueueElem; + +static OutputQueue* output_queue_new(GOutputStream *output) +{ + OutputQueue *queue = g_new0(OutputQueue, 1); + + queue->output = g_object_ref(output); + queue->queue = g_queue_new(); + + return queue; +} + +static void output_queue_free(OutputQueue *queue) +{ + g_warn_if_fail(g_queue_get_length(queue->queue) == 0); + g_warn_if_fail(!queue->flushing); + + g_queue_free_full(queue->queue, g_free); + g_clear_object(&queue->output); + if (queue->idle_id) + g_source_remove(queue->idle_id); + g_free(queue); +} + +static gboolean output_queue_idle(gpointer user_data); + +static void output_queue_flush_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + OutputQueueElem *e = user_data; + OutputQueue *q = e->queue; + + q->flushing = FALSE; + g_output_stream_flush_finish(G_OUTPUT_STREAM(source_object), + res, &error); + if (error) + g_warning("error: %s", error->message); + + g_clear_error(&error); + + if (!q->idle_id) + q->idle_id = g_idle_add(output_queue_idle, q); + + g_free(e); +} + +static gboolean output_queue_idle(gpointer user_data) +{ + OutputQueue *q = user_data; + OutputQueueElem *e; + GError *error = NULL; + + if (q->flushing) { + q->idle_id = 0; + return FALSE; + } + + e = g_queue_pop_head(q->queue); + if (!e) { + q->idle_id = 0; + return FALSE; + } + + if (!g_output_stream_write_all(q->output, e->buf, e->size, NULL, NULL, &error)) + goto err; + else if (e->pushed_cb) + e->pushed_cb(q, e->user_data); + + q->flushing = TRUE; + g_output_stream_flush_async(q->output, G_PRIORITY_DEFAULT, NULL, output_queue_flush_cb, e); + + return TRUE; + +err: + g_warning("failed to write to output stream"); + if (error) + g_warning("error: %s", error->message); + g_clear_error(&error); + + q->idle_id = 0; + return FALSE; +} + +static void output_queue_push(OutputQueue *q, const guint8 *buf, gsize size, + GFunc pushed_cb, gpointer user_data) +{ + OutputQueueElem *e = g_new(OutputQueueElem, 1); + + e->buf = buf; + e->size = size; + e->pushed_cb = pushed_cb; + e->user_data = user_data; + e->queue = q; + g_queue_push_tail(q->queue, e); + + if (!q->idle_id && !q->flushing) + q->idle_id = g_idle_add(output_queue_idle, q); +} + +typedef struct Client +{ + guint refs; + SpiceWebdavChannel *self; + GIOStream *pipe; + gint64 id; + GCancellable *cancellable; + + struct _mux { + gint64 id; + guint16 size; + guint8 *buf; + } mux; +} Client; + +static void +client_unref(Client *client) +{ + if (--client->refs > 0) + return; + + g_free(client->mux.buf); + + g_object_unref(client->pipe); + g_object_unref(client->cancellable); + + g_free(client); +} + +static Client * +client_ref(Client *client) +{ + client->refs++; + return client; +} + +static void client_start_read(SpiceWebdavChannel *self, Client *client); + +static void remove_client(SpiceWebdavChannel *self, Client *client) +{ + SpiceWebdavChannelPrivate *c; + + if (g_cancellable_is_cancelled(client->cancellable)) + return; + + g_cancellable_cancel(client->cancellable); + + c = self->priv; + g_hash_table_remove(c->clients, &client->id); +} + +static void mux_pushed_cb(OutputQueue *q, gpointer user_data) +{ + Client *client = user_data; + + if (client->mux.size == 0) { + remove_client(client->self, client); + } else { + client_start_read(client->self, client); + } + + client_unref(client); +} + +#define MAX_MUX_SIZE G_MAXUINT16 + +static void server_reply_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + Client *client = user_data; + SpiceWebdavChannel *self = client->self; + SpiceWebdavChannelPrivate *c = self->priv; + GError *err = NULL; + gssize size; + + size = g_input_stream_read_finish(G_INPUT_STREAM(source_object), res, &err); + if (err || g_cancellable_is_cancelled(client->cancellable)) + goto end; + + g_return_if_fail(size <= MAX_MUX_SIZE); + g_return_if_fail(size >= 0); + client->mux.size = size; + + output_queue_push(c->queue, (guint8 *)&client->mux.id, sizeof(gint64), NULL, NULL); + client->mux.size = GUINT16_TO_LE(client->mux.size); + output_queue_push(c->queue, (guint8 *)&client->mux.size, sizeof(guint16), NULL, NULL); + output_queue_push(c->queue, (guint8 *)client->mux.buf, size, (GFunc)mux_pushed_cb, client); + + return; + +end: + if (err) { + if (!g_cancellable_is_cancelled(client->cancellable)) + g_warning("read error: %s", err->message); + remove_client(self, client); + g_clear_error(&err); + } + + client_unref(client); +} + +static void client_start_read(SpiceWebdavChannel *self, Client *client) +{ + GInputStream *input; + + input = g_io_stream_get_input_stream(G_IO_STREAM(client->pipe)); + g_input_stream_read_async(input, client->mux.buf, MAX_MUX_SIZE, + G_PRIORITY_DEFAULT, client->cancellable, server_reply_cb, + client_ref(client)); +} + +static void start_demux(SpiceWebdavChannel *self); + +#ifdef USE_PHODAV +static void demux_to_client_finish(SpiceWebdavChannel *self, + Client *client, gboolean fail) +{ + SpiceWebdavChannelPrivate *c = self->priv; + + if (fail) { + remove_client(self, client); + } + + c->demuxing = FALSE; + start_demux(self); +} + +static void demux_to_client_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Client *client = user_data; + SpiceWebdavChannelPrivate *c = client->self->priv; + GError *error = NULL; + gboolean fail; + gsize size; + + g_output_stream_write_all_finish(G_OUTPUT_STREAM(source), result, &size, &error); + + if (error) { + CHANNEL_DEBUG(client->self, "write failed: %s", error->message); + g_clear_error(&error); + } + + fail = (size != c->demux.size); + g_warn_if_fail(size == c->demux.size); + demux_to_client_finish(client->self, client, fail); +} +#endif + +static void demux_to_client(SpiceWebdavChannel *self, + Client *client) +{ +#ifdef USE_PHODAV + SpiceWebdavChannelPrivate *c = self->priv; + gsize size = c->demux.size; + + CHANNEL_DEBUG(self, "pushing %"G_GSIZE_FORMAT" to client %p", size, client); + + if (size > 0) { + g_output_stream_write_all_async(g_io_stream_get_output_stream(client->pipe), + c->demux.buf, size, G_PRIORITY_DEFAULT, + c->cancellable, demux_to_client_cb, client); + return; + } else { + /* Nothing to write */ + demux_to_client_finish(self, client, FALSE); + } +#endif +} + +static void start_client(SpiceWebdavChannel *self) +{ +#ifdef USE_PHODAV + SpiceWebdavChannelPrivate *c = self->priv; + Client *client; + GIOStream *peer = NULL; + SpiceSession *session; + SoupServer *server; + GSocketAddress *addr; + GError *error = NULL; + + session = spice_channel_get_session(SPICE_CHANNEL(self)); + server = phodav_server_get_soup_server(spice_session_get_webdav_server(session)); + + CHANNEL_DEBUG(self, "starting client %" G_GINT64_FORMAT, c->demux.client); + + client = g_new0(Client, 1); + client->refs = 1; + client->id = c->demux.client; + client->self = self; + client->mux.id = GINT64_TO_LE(client->id); + client->mux.buf = g_malloc0(MAX_MUX_SIZE); + client->cancellable = g_cancellable_new(); + spice_make_pipe(&client->pipe, &peer); + + addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + if (!soup_server_accept_iostream(server, peer, addr, addr, &error)) + goto fail; + + g_hash_table_insert(c->clients, &client->id, client); + + client_start_read(self, client); + demux_to_client(self, client); + + g_clear_object(&addr); + return; + +fail: + if (error) + CHANNEL_DEBUG(self, "failed to start client: %s", error->message); + + g_clear_object(&addr); + g_clear_object(&peer); + g_clear_error(&error); + client_unref(client); +#endif +} + +static void data_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceWebdavChannel *self = user_data; + SpiceWebdavChannelPrivate *c; + Client *client; + GError *error = NULL; + gssize size; + + size = spice_vmc_input_stream_read_all_finish(G_INPUT_STREAM(source_object), res, &error); + if (error) { + g_warning("error: %s", error->message); + g_clear_error(&error); + return; + } + + c = self->priv; + g_return_if_fail(size == c->demux.size); + + client = g_hash_table_lookup(c->clients, &c->demux.client); + + if (client) + demux_to_client(self, client); + else + start_client(self); +} + + +static void size_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceWebdavChannel *self = user_data; + SpiceWebdavChannelPrivate *c; + GInputStream *istream = G_INPUT_STREAM(source_object); + GError *error = NULL; + gssize size; + + size = spice_vmc_input_stream_read_all_finish(G_INPUT_STREAM(source_object), res, &error); + if (error || size != sizeof(guint16)) + goto end; + + c = self->priv; + c->demux.size = GUINT16_FROM_LE(c->demux.size); + spice_vmc_input_stream_read_all_async(istream, + c->demux.buf, c->demux.size, + G_PRIORITY_DEFAULT, c->cancellable, data_read_cb, self); + return; + +end: + if (error) { + g_warning("error: %s", error->message); + g_clear_error(&error); + } +} + +static void client_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceWebdavChannel *self = user_data; + SpiceWebdavChannelPrivate *c = self->priv; + GInputStream *istream = G_INPUT_STREAM(source_object); + GError *error = NULL; + gssize size; + + size = spice_vmc_input_stream_read_all_finish(G_INPUT_STREAM(source_object), res, &error); + if (error || size != sizeof(gint64)) + goto end; + + c->demux.client = GINT64_FROM_LE(c->demux.client); + spice_vmc_input_stream_read_all_async(istream, + &c->demux.size, sizeof(guint16), + G_PRIORITY_DEFAULT, c->cancellable, size_read_cb, self); + return; + +end: + if (error) { + g_warning("error: %s", error->message); + g_clear_error(&error); + } +} + +static void start_demux(SpiceWebdavChannel *self) +{ + SpiceWebdavChannelPrivate *c = self->priv; + GInputStream *istream = g_io_stream_get_input_stream(G_IO_STREAM(c->stream)); + + if (c->demuxing) + return; + + c->demuxing = TRUE; + + CHANNEL_DEBUG(self, "start demux"); + spice_vmc_input_stream_read_all_async(istream, &c->demux.client, sizeof(gint64), + G_PRIORITY_DEFAULT, c->cancellable, client_read_cb, self); + +} + +static void port_event(SpiceWebdavChannel *self, gint event) +{ + SpiceWebdavChannelPrivate *c = self->priv; + + CHANNEL_DEBUG(self, "port event:%d", event); + if (event == SPICE_PORT_EVENT_OPENED) { + g_cancellable_reset(c->cancellable); + start_demux(self); + } else { + g_cancellable_cancel(c->cancellable); + c->demuxing = FALSE; + g_hash_table_remove_all(c->clients); + } +} + +static void client_remove_unref(gpointer data) +{ + Client *client = data; + + g_cancellable_cancel(client->cancellable); + client_unref(client); +} + +static void spice_webdav_channel_init(SpiceWebdavChannel *channel) +{ + SpiceWebdavChannelPrivate *c = SPICE_WEBDAV_CHANNEL_GET_PRIVATE(channel); + + channel->priv = c; + c->stream = spice_vmc_stream_new(SPICE_CHANNEL(channel)); + c->cancellable = g_cancellable_new(); + c->clients = g_hash_table_new_full(g_int64_hash, g_int64_equal, + NULL, client_remove_unref); + c->demux.buf = g_malloc0(MAX_MUX_SIZE); + + GOutputStream *ostream = g_io_stream_get_output_stream(G_IO_STREAM(c->stream)); + c->queue = output_queue_new(ostream); +} + +static void spice_webdav_channel_finalize(GObject *object) +{ + SpiceWebdavChannelPrivate *c = SPICE_WEBDAV_CHANNEL(object)->priv; + + g_free(c->demux.buf); + + G_OBJECT_CLASS(spice_webdav_channel_parent_class)->finalize(object); +} + +static void spice_webdav_channel_dispose(GObject *object) +{ + SpiceWebdavChannelPrivate *c = SPICE_WEBDAV_CHANNEL(object)->priv; + + g_cancellable_cancel(c->cancellable); + g_clear_object(&c->cancellable); + g_clear_pointer(&c->queue, output_queue_free); + g_clear_object(&c->stream); + g_hash_table_unref(c->clients); + + G_OBJECT_CLASS(spice_webdav_channel_parent_class)->dispose(object); +} + +static void spice_webdav_channel_up(SpiceChannel *channel) +{ + CHANNEL_DEBUG(channel, "up"); +} + +static void spice_webdav_channel_class_init(SpiceWebdavChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass); + + gobject_class->dispose = spice_webdav_channel_dispose; + gobject_class->finalize = spice_webdav_channel_finalize; + channel_class->handle_msg = spice_webdav_handle_msg; + channel_class->channel_up = spice_webdav_channel_up; + + g_signal_override_class_handler("port-event", + SPICE_TYPE_WEBDAV_CHANNEL, + G_CALLBACK(port_event)); + + g_type_class_add_private(klass, sizeof(SpiceWebdavChannelPrivate)); +} + +/* coroutine context */ +static void webdav_handle_msg(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceWebdavChannel *self = SPICE_WEBDAV_CHANNEL(channel); + SpiceWebdavChannelPrivate *c = self->priv; + int size; + uint8_t *buf; + + buf = spice_msg_in_raw(in, &size); + CHANNEL_DEBUG(channel, "len:%d buf:%p", size, buf); + + spice_vmc_input_stream_co_data( + SPICE_VMC_INPUT_STREAM(g_io_stream_get_input_stream(G_IO_STREAM(c->stream))), + buf, size); +} + + +/* coroutine context */ +static void spice_webdav_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg) +{ + int type = spice_msg_in_type(msg); + SpiceChannelClass *parent_class; + + parent_class = SPICE_CHANNEL_CLASS(spice_webdav_channel_parent_class); + + if (type == SPICE_MSG_SPICEVMC_DATA) + webdav_handle_msg(channel, msg); + else if (parent_class->handle_msg) + parent_class->handle_msg(channel, msg); + else + g_return_if_reached(); +} diff --git a/src/channel-webdav.h b/src/channel-webdav.h new file mode 100644 index 0000000..45bcb28 --- /dev/null +++ b/src/channel-webdav.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_WEBDAV_CHANNEL_H__ +#define __SPICE_WEBDAV_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include "spice-client.h" +#include "channel-port.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_WEBDAV_CHANNEL (spice_webdav_channel_get_type()) +#define SPICE_WEBDAV_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_WEBDAV_CHANNEL, SpiceWebdavChannel)) +#define SPICE_WEBDAV_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_WEBDAV_CHANNEL, SpiceWebdavChannelClass)) +#define SPICE_IS_WEBDAV_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_WEBDAV_CHANNEL)) +#define SPICE_IS_WEBDAV_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_WEBDAV_CHANNEL)) +#define SPICE_WEBDAV_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_WEBDAV_CHANNEL, SpiceWebdavChannelClass)) + +typedef struct _SpiceWebdavChannel SpiceWebdavChannel; +typedef struct _SpiceWebdavChannelClass SpiceWebdavChannelClass; +typedef struct _SpiceWebdavChannelPrivate SpiceWebdavChannelPrivate; + +/** + * SpiceWebdavChannel: + * + * The #SpiceWebdavChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceWebdavChannel { + SpicePortChannel parent; + + /*< private >*/ + SpiceWebdavChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceWebdavChannelClass: + * @parent_class: Parent class. + * + * Class structure for #SpiceWebdavChannel. + */ +struct _SpiceWebdavChannelClass { + SpicePortChannelClass parent_class; + + /*< private >*/ + /* Do not add fields to this struct */ +}; + +GType spice_webdav_channel_get_type(void); + +G_END_DECLS + +#endif /* __SPICE_WEBDAV_CHANNEL_H__ */ diff --git a/src/client_sw_canvas.c b/src/client_sw_canvas.c new file mode 100644 index 0000000..a69abe0 --- /dev/null +++ b/src/client_sw_canvas.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#define SW_CANVAS_CACHE + +#include "common/sw_canvas.c" diff --git a/src/client_sw_canvas.h b/src/client_sw_canvas.h new file mode 100644 index 0000000..1180c5b --- /dev/null +++ b/src/client_sw_canvas.h @@ -0,0 +1,25 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_SW_CANVAS_H__ +#define __SPICE_CLIENT_SW_CANVAS_H__ + +#define SW_CANVAS_CACHE + +#include + +#endif /* __SPICE_CLIENT_SW_CANVAS_H__ */ diff --git a/src/continuation.c b/src/continuation.c new file mode 100644 index 0000000..adce858 --- /dev/null +++ b/src/continuation.c @@ -0,0 +1,102 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "config.h" + +/* keep this above system headers, but below config.h */ +#ifdef _FORTIFY_SOURCE +#undef _FORTIFY_SOURCE +#endif + +#include +#include + +#include "continuation.h" + +/* + * va_args to makecontext() must be type 'int', so passing + * the pointer we need may require several int args. This + * union is a quick hack to let us do that + */ +union cc_arg { + void *p; + int i[2]; +}; + +static void continuation_trampoline(int i0, int i1) +{ + union cc_arg arg; + struct continuation *cc; + arg.i[0] = i0; + arg.i[1] = i1; + cc = arg.p; + + if (_setjmp(cc->jmp) == 0) { + ucontext_t tmp; + swapcontext(&tmp, &cc->last); + } + + cc->entry(cc); +} + +void cc_init(struct continuation *cc) +{ + volatile union cc_arg arg; + arg.p = cc; + if (getcontext(&cc->uc) == -1) + g_error("getcontext() failed: %s", g_strerror(errno)); + cc->uc.uc_link = &cc->last; + cc->uc.uc_stack.ss_sp = cc->stack; + cc->uc.uc_stack.ss_size = cc->stack_size; + cc->uc.uc_stack.ss_flags = 0; + + makecontext(&cc->uc, (void *)continuation_trampoline, 2, arg.i[0], arg.i[1]); + swapcontext(&cc->last, &cc->uc); +} + +int cc_release(struct continuation *cc) +{ + if (cc->release) + return cc->release(cc); + + return 0; +} + +int cc_swap(struct continuation *from, struct continuation *to) +{ + to->exited = 0; + if (getcontext(&to->last) == -1) + return -1; + else if (to->exited == 0) + to->exited = 1; // so when coroutine finishes + else if (to->exited == 1) + return 1; // it ends up here + + if (_setjmp(from->jmp) == 0) + _longjmp(to->jmp, 1); + + return 0; +} +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/continuation.h b/src/continuation.h new file mode 100644 index 0000000..675a257 --- /dev/null +++ b/src/continuation.h @@ -0,0 +1,61 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _CONTINUATION_H_ +#define _CONTINUATION_H_ + +#include +#include +#include + +struct continuation +{ + char *stack; + size_t stack_size; + void (*entry)(struct continuation *cc); + int (*release)(struct continuation *cc); + + /* private */ + ucontext_t uc; + ucontext_t last; + int exited; + jmp_buf jmp; +}; + +void cc_init(struct continuation *cc); + +int cc_release(struct continuation *cc); + +/* you can use an uninitialized struct continuation for from if you do not have + the current continuation handy. */ +int cc_swap(struct continuation *from, struct continuation *to); + +#define offset_of(type, member) ((unsigned long)(&((type *)0)->member)) +#define container_of(obj, type, member) \ + (type *)(((char *)obj) - offset_of(type, member)) + +#endif +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/controller/Makefile.am b/src/controller/Makefile.am new file mode 100644 index 0000000..fb56986 --- /dev/null +++ b/src/controller/Makefile.am @@ -0,0 +1,101 @@ +NULL = + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"GSpiceController\" \ + $(GIO_CFLAGS) \ + $(COMMON_CFLAGS) \ + -Wno-deprecated-declarations \ + $(NULL) + +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +AM_LDFLAGS = \ + -no-undefined \ + $(GIO_LIBS) \ + $(NULL) + +AM_VALAFLAGS = \ + --pkg gio-2.0 \ + --pkg spice-protocol --vapidir=$(top_srcdir)/data \ + --pkg custom --vapidir=$(srcdir) \ + -C \ + $(NULL) + +lib_LTLIBRARIES = libspice-controller.la +noinst_PROGRAMS = test-controller spice-controller-dump + +libspice_controller_la_VALASOURCES = \ + menu.vala \ + controller.vala \ + foreign-menu.vala \ + util.vala \ + $(NULL) + +libspice_controller_la_BUILT_SOURCES = \ + $(libspice_controller_la_VALASOURCES:.vala=.c) \ + spice-controller.h \ + $(NULL) + +BUILT_SOURCES = \ + $(libspice_controller_la_BUILT_SOURCES) \ + controller.vala.stamp \ + $(NULL) + +libspice_controller_la_SOURCES = \ + $(libspice_controller_la_BUILT_SOURCES) \ + custom.h \ + spice-controller-listener.c \ + spice-controller-listener.h \ + spice-foreign-menu-listener.c \ + spice-foreign-menu-listener.h \ + $(NULL) + +if OS_WIN32 +libspice_controller_la_SOURCES += \ + namedpipe.c \ + namedpipe.h \ + namedpipeconnection.c \ + namedpipeconnection.h \ + namedpipelistener.c \ + namedpipelistener.h \ + win32-util.c \ + win32-util.h \ + $(NULL) +endif +libspice_controller_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -version-info 0:0:0 \ + $(NULL) + +libspice_controllerincludedir = $(includedir)/spice-controller +libspice_controllerinclude_HEADERS = \ + spice-controller.h + +test_controller_SOURCES = test.c +test_controller_LDADD = libspice-controller.la + +spice_controller_dump_SOURCES = dump.c +spice_controller_dump_LDADD = libspice-controller.la + +controller.vala.stamp: $(libspice_controller_la_VALASOURCES) custom.vapi + @if test -z "$(VALAC)"; then \ + echo "" ; \ + echo " *** Error: missing valac!" ; \ + echo " *** You must run autogen.sh or configure --enable-vala" ; \ + echo "" ; \ + exit 1 ; \ + fi + $(VALA_V)$(VALAC) $(VALAFLAGS) $(AM_VALAFLAGS) \ + $(addprefix $(srcdir)/,$(libspice_controller_la_VALASOURCES)) \ + -H spice-controller.h + @touch $@ + +$(libspice_controller_la_BUILT_SOURCES): controller.vala.stamp + +EXTRA_DIST = \ + $(libspice_controller_la_VALASOURCES) \ + controller.vala.stamp \ + custom.vapi \ + gio-windows-2.0.vapi \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/src/controller/Makefile.in b/src/controller/Makefile.in new file mode 100644 index 0000000..b3b3bc2 --- /dev/null +++ b/src/controller/Makefile.in @@ -0,0 +1,948 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-controller$(EXEEXT) \ + spice-controller-dump$(EXEEXT) +@OS_WIN32_TRUE@am__append_1 = \ +@OS_WIN32_TRUE@ namedpipe.c \ +@OS_WIN32_TRUE@ namedpipe.h \ +@OS_WIN32_TRUE@ namedpipeconnection.c \ +@OS_WIN32_TRUE@ namedpipeconnection.h \ +@OS_WIN32_TRUE@ namedpipelistener.c \ +@OS_WIN32_TRUE@ namedpipelistener.h \ +@OS_WIN32_TRUE@ win32-util.c \ +@OS_WIN32_TRUE@ win32-util.h \ +@OS_WIN32_TRUE@ $(NULL) + +subdir = src/controller +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am \ + $(libspice_controllerinclude_HEADERS) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(libspice_controllerincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libspice_controller_la_LIBADD = +am__libspice_controller_la_SOURCES_DIST = menu.c controller.c \ + foreign-menu.c util.c spice-controller.h custom.h \ + spice-controller-listener.c spice-controller-listener.h \ + spice-foreign-menu-listener.c spice-foreign-menu-listener.h \ + namedpipe.c namedpipe.h namedpipeconnection.c \ + namedpipeconnection.h namedpipelistener.c namedpipelistener.h \ + win32-util.c win32-util.h +am__objects_1 = +am__objects_2 = menu.lo controller.lo foreign-menu.lo util.lo \ + $(am__objects_1) +am__objects_3 = $(am__objects_2) $(am__objects_1) +@OS_WIN32_TRUE@am__objects_4 = namedpipe.lo namedpipeconnection.lo \ +@OS_WIN32_TRUE@ namedpipelistener.lo win32-util.lo \ +@OS_WIN32_TRUE@ $(am__objects_1) +am_libspice_controller_la_OBJECTS = $(am__objects_3) \ + spice-controller-listener.lo spice-foreign-menu-listener.lo \ + $(am__objects_1) $(am__objects_4) +libspice_controller_la_OBJECTS = $(am_libspice_controller_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libspice_controller_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libspice_controller_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +PROGRAMS = $(noinst_PROGRAMS) +am_spice_controller_dump_OBJECTS = dump.$(OBJEXT) +spice_controller_dump_OBJECTS = $(am_spice_controller_dump_OBJECTS) +spice_controller_dump_DEPENDENCIES = libspice-controller.la +am_test_controller_OBJECTS = test.$(OBJEXT) +test_controller_OBJECTS = $(am_test_controller_OBJECTS) +test_controller_DEPENDENCIES = libspice-controller.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libspice_controller_la_SOURCES) \ + $(spice_controller_dump_SOURCES) $(test_controller_SOURCES) +DIST_SOURCES = $(am__libspice_controller_la_SOURCES_DIST) \ + $(spice_controller_dump_SOURCES) $(test_controller_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(libspice_controllerinclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"GSpiceController\" \ + $(GIO_CFLAGS) \ + $(COMMON_CFLAGS) \ + -Wno-deprecated-declarations \ + $(NULL) + + +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +AM_LDFLAGS = \ + -no-undefined \ + $(GIO_LIBS) \ + $(NULL) + +AM_VALAFLAGS = \ + --pkg gio-2.0 \ + --pkg spice-protocol --vapidir=$(top_srcdir)/data \ + --pkg custom --vapidir=$(srcdir) \ + -C \ + $(NULL) + +lib_LTLIBRARIES = libspice-controller.la +libspice_controller_la_VALASOURCES = \ + menu.vala \ + controller.vala \ + foreign-menu.vala \ + util.vala \ + $(NULL) + +libspice_controller_la_BUILT_SOURCES = \ + $(libspice_controller_la_VALASOURCES:.vala=.c) \ + spice-controller.h \ + $(NULL) + +BUILT_SOURCES = \ + $(libspice_controller_la_BUILT_SOURCES) \ + controller.vala.stamp \ + $(NULL) + +libspice_controller_la_SOURCES = \ + $(libspice_controller_la_BUILT_SOURCES) custom.h \ + spice-controller-listener.c spice-controller-listener.h \ + spice-foreign-menu-listener.c spice-foreign-menu-listener.h \ + $(NULL) $(am__append_1) +libspice_controller_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -version-info 0:0:0 \ + $(NULL) + +libspice_controllerincludedir = $(includedir)/spice-controller +libspice_controllerinclude_HEADERS = \ + spice-controller.h + +test_controller_SOURCES = test.c +test_controller_LDADD = libspice-controller.la +spice_controller_dump_SOURCES = dump.c +spice_controller_dump_LDADD = libspice-controller.la +EXTRA_DIST = \ + $(libspice_controller_la_VALASOURCES) \ + controller.vala.stamp \ + custom.vapi \ + gio-windows-2.0.vapi \ + $(NULL) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/controller/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/controller/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libspice-controller.la: $(libspice_controller_la_OBJECTS) $(libspice_controller_la_DEPENDENCIES) $(EXTRA_libspice_controller_la_DEPENDENCIES) + $(AM_V_CCLD)$(libspice_controller_la_LINK) -rpath $(libdir) $(libspice_controller_la_OBJECTS) $(libspice_controller_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +spice-controller-dump$(EXEEXT): $(spice_controller_dump_OBJECTS) $(spice_controller_dump_DEPENDENCIES) $(EXTRA_spice_controller_dump_DEPENDENCIES) + @rm -f spice-controller-dump$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(spice_controller_dump_OBJECTS) $(spice_controller_dump_LDADD) $(LIBS) + +test-controller$(EXEEXT): $(test_controller_OBJECTS) $(test_controller_DEPENDENCIES) $(EXTRA_test_controller_DEPENDENCIES) + @rm -f test-controller$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_controller_OBJECTS) $(test_controller_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foreign-menu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namedpipe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namedpipeconnection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namedpipelistener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-controller-listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spice-foreign-menu-listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32-util.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libspice_controllerincludeHEADERS: $(libspice_controllerinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libspice_controllerinclude_HEADERS)'; test -n "$(libspice_controllerincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libspice_controllerincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libspice_controllerincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libspice_controllerincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libspice_controllerincludedir)" || exit $$?; \ + done + +uninstall-libspice_controllerincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libspice_controllerinclude_HEADERS)'; test -n "$(libspice_controllerincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libspice_controllerincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libspice_controllerincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-libspice_controllerincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-libspice_controllerincludeHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libspice_controllerincludeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-libLTLIBRARIES \ + uninstall-libspice_controllerincludeHEADERS + +.PRECIOUS: Makefile + + +controller.vala.stamp: $(libspice_controller_la_VALASOURCES) custom.vapi + @if test -z "$(VALAC)"; then \ + echo "" ; \ + echo " *** Error: missing valac!" ; \ + echo " *** You must run autogen.sh or configure --enable-vala" ; \ + echo "" ; \ + exit 1 ; \ + fi + $(VALA_V)$(VALAC) $(VALAFLAGS) $(AM_VALAFLAGS) \ + $(addprefix $(srcdir)/,$(libspice_controller_la_VALASOURCES)) \ + -H spice-controller.h + @touch $@ + +$(libspice_controller_la_BUILT_SOURCES): controller.vala.stamp + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/controller/controller.c b/src/controller/controller.c new file mode 100644 index 0000000..f9baf67 --- /dev/null +++ b/src/controller/controller.c @@ -0,0 +1,2405 @@ +/* controller.c generated by valac 0.32.0, the Vala compiler + * generated from controller.vala, do not modify */ + +/* Copyright (C) 2011 Red Hat, Inc.*/ +/* This library is free software; you can redistribute it and/or*/ +/* modify it under the terms of the GNU Lesser General Public*/ +/* License as published by the Free Software Foundation; either*/ +/* version 2.1 of the License, or (at your option) any later version.*/ +/* This library is distributed in the hope that it will be useful,*/ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of*/ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU*/ +/* Lesser General Public License for more details.*/ +/* You should have received a copy of the GNU Lesser General Public*/ +/* License along with this library; if not, see .*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SPICE_CTRL_TYPE_CONTROLLER (spice_ctrl_controller_get_type ()) +#define SPICE_CTRL_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlController)) +#define SPICE_CTRL_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlControllerClass)) +#define SPICE_CTRL_IS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_CONTROLLER)) +#define SPICE_CTRL_IS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_CONTROLLER)) +#define SPICE_CTRL_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlControllerClass)) + +typedef struct _SpiceCtrlController SpiceCtrlController; +typedef struct _SpiceCtrlControllerClass SpiceCtrlControllerClass; +typedef struct _SpiceCtrlControllerPrivate SpiceCtrlControllerPrivate; + +#define SPICE_CTRL_TYPE_MENU (spice_ctrl_menu_get_type ()) +#define SPICE_CTRL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenu)) +#define SPICE_CTRL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) +#define SPICE_CTRL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) + +typedef struct _SpiceCtrlMenu SpiceCtrlMenu; +typedef struct _SpiceCtrlMenuClass SpiceCtrlMenuClass; +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define __g_list_free__g_object_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__g_object_unref0_ (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +typedef struct _SpiceCtrlControllerSendMsgData SpiceCtrlControllerSendMsgData; +typedef struct _SpiceCtrlControllerHandleClientData SpiceCtrlControllerHandleClientData; +typedef struct _SpiceCtrlControllerListenData SpiceCtrlControllerListenData; + +typedef enum { + SPICE_CTRL_ERROR_VALUE +} SpiceCtrlError; +#define SPICE_CTRL_ERROR spice_ctrl_error_quark () +struct _SpiceCtrlController { + GObject parent_instance; + SpiceCtrlControllerPrivate * priv; +}; + +struct _SpiceCtrlControllerClass { + GObjectClass parent_class; +}; + +struct _SpiceCtrlControllerPrivate { + gchar* _host; + guint32 _port; + guint32 _sport; + gchar* _password; + unsigned int _display_flags; + gchar* _tls_ciphers; + gchar* _host_subject; + gchar* _ca_file; + gchar* _title; + gchar* _hotkeys; + gchar** _secure_channels; + gint _secure_channels_length1; + gint __secure_channels_size_; + gchar** _disable_channels; + gint _disable_channels_length1; + gint __disable_channels_size_; + SpiceCtrlMenu* _menu; + gboolean _enable_smartcard; + gboolean _send_cad; + gchar** _disable_effects; + gint _disable_effects_length1; + gint __disable_effects_size_; + guint32 _color_depth; + gboolean _enable_usbredir; + gboolean _enable_usb_autoshare; + gchar* _usb_filter; + gchar* _proxy; + GIOStream* excl_connection; + gint nclients; + GList* clients; +}; + +struct _SpiceCtrlControllerSendMsgData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlController* self; + guint8* p; + gint p_length1; + gboolean result; + GIOStream* _tmp0_; + GIOStream* _tmp1_; + GOutputStream* _tmp2_; + GOutputStream* _tmp3_; + guint8* _tmp4_; + gint _tmp4__length1; + guint8* _tmp5_; + gint _tmp5__length1; + GList* _tmp6_; + GList* c_collection; + GList* c_it; + GIOStream* _tmp7_; + GIOStream* c; + GIOStream* _tmp8_; + GOutputStream* _tmp9_; + GOutputStream* _tmp10_; + guint8* _tmp11_; + gint _tmp11__length1; + guint8* _tmp12_; + gint _tmp12__length1; + GError* e; + GError* _tmp13_; + const gchar* _tmp14_; + GError * _inner_error_; +}; + +struct _SpiceCtrlControllerHandleClientData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlController* self; + GIOStream* c; + gboolean excl; + guint8* p; + guint8* _tmp0_; + gint p_length1; + gint _p_size_; + ControllerInit* init; + guint8* _tmp1_; + gint _tmp1__length1; + GIOStream* _tmp2_; + GInputStream* _tmp3_; + GInputStream* _tmp4_; + guint8* _tmp5_; + gint _tmp5__length1; + ControllerInit* _tmp6_; + ControllerInitHeader _tmp7_; + guint32 _tmp8_; + gboolean _tmp9_; + ControllerInit* _tmp10_; + ControllerInitHeader _tmp11_; + guint32 _tmp12_; + gboolean _tmp13_; + ControllerInit* _tmp14_; + ControllerInitHeader _tmp15_; + guint32 _tmp16_; + gboolean _tmp17_; + ControllerInit* _tmp18_; + guint64 _tmp19_; + gboolean _tmp20_; + GIOStream* _tmp21_; + gboolean _tmp22_; + ControllerInit* _tmp23_; + guint32 _tmp24_; + gboolean _tmp25_; + gint _tmp26_; + gint _tmp27_; + gchar* _tmp28_; + gchar* _tmp29_; + gchar* _tmp30_; + gchar* _tmp31_; + GIOStream* _tmp32_; + GIOStream* _tmp33_; + gboolean _tmp34_; + guint8* t; + guint8* _tmp35_; + gint t_length1; + gint _t_size_; + GIOStream* _tmp36_; + GInputStream* _tmp37_; + GInputStream* _tmp38_; + guint8* _tmp39_; + gint _tmp39__length1; + ControllerMsg* msg; + guint8* _tmp40_; + gint _tmp40__length1; + ControllerMsg* _tmp41_; + guint32 _tmp42_; + gchar* _tmp43_; + gchar* _tmp44_; + gchar* _tmp45_; + gchar* _tmp46_; + gchar* _tmp47_; + gchar* _tmp48_; + ControllerMsg* _tmp49_; + guint32 _tmp50_; + gchar* _tmp51_; + gchar* _tmp52_; + gchar* _tmp53_; + gchar* _tmp54_; + ControllerMsg* _tmp55_; + guint32 _tmp56_; + gboolean _tmp57_; + ControllerMsg* _tmp58_; + guint32 _tmp59_; + ControllerMsg* _tmp60_; + guint32 _tmp61_; + gint _tmp62_; + guint8* _tmp63_; + gint _tmp63__length1; + GIOStream* _tmp64_; + GInputStream* _tmp65_; + GInputStream* _tmp66_; + guint8* _tmp67_; + gint _tmp67__length1; + ControllerMsg* _tmp68_; + guint32 _tmp69_; + ControllerMsg* _tmp70_; + gboolean _tmp71_; + GError * _inner_error_; +}; + +struct _SpiceCtrlControllerListenData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlController* self; + gchar* addr; + GObject* listener; + const gchar* _tmp0_; + GObject* _tmp1_; + gboolean _tmp2_; + GIOStream* c; + GObject* _tmp3_; + GIOStream* _tmp4_; + GIOStream* _tmp5_; + gint _tmp6_; + GIOStream* _tmp7_; + GIOStream* _tmp8_; + GIOStream* _tmp9_; + GError* e; + GError* _tmp10_; + const gchar* _tmp11_; + GIOStream* _tmp12_; + GIOStream* _tmp13_; + gint _tmp14_; + GError * _inner_error_; +}; + + +static gpointer spice_ctrl_controller_parent_class = NULL; + +GQuark spice_ctrl_error_quark (void); +GType spice_ctrl_controller_get_type (void) G_GNUC_CONST; +GType spice_ctrl_menu_get_type (void) G_GNUC_CONST; +#define SPICE_CTRL_CONTROLLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlControllerPrivate)) +enum { + SPICE_CTRL_CONTROLLER_DUMMY_PROPERTY, + SPICE_CTRL_CONTROLLER_HOST, + SPICE_CTRL_CONTROLLER_PORT, + SPICE_CTRL_CONTROLLER_SPORT, + SPICE_CTRL_CONTROLLER_PASSWORD, + SPICE_CTRL_CONTROLLER_DISPLAY_FLAGS, + SPICE_CTRL_CONTROLLER_TLS_CIPHERS, + SPICE_CTRL_CONTROLLER_HOST_SUBJECT, + SPICE_CTRL_CONTROLLER_CA_FILE, + SPICE_CTRL_CONTROLLER_TITLE, + SPICE_CTRL_CONTROLLER_HOTKEYS, + SPICE_CTRL_CONTROLLER_SECURE_CHANNELS, + SPICE_CTRL_CONTROLLER_DISABLE_CHANNELS, + SPICE_CTRL_CONTROLLER_MENU, + SPICE_CTRL_CONTROLLER_ENABLE_SMARTCARD, + SPICE_CTRL_CONTROLLER_SEND_CAD, + SPICE_CTRL_CONTROLLER_DISABLE_EFFECTS, + SPICE_CTRL_CONTROLLER_COLOR_DEPTH, + SPICE_CTRL_CONTROLLER_ENABLE_USBREDIR, + SPICE_CTRL_CONTROLLER_ENABLE_USB_AUTOSHARE, + SPICE_CTRL_CONTROLLER_USB_FILTER, + SPICE_CTRL_CONTROLLER_PROXY +}; +static void _g_object_unref0_ (gpointer var); +static void _g_list_free__g_object_unref0_ (GList* self); +void spice_ctrl_controller_menu_item_click_msg (SpiceCtrlController* self, gint32 item_id); +void spice_ctrl_controller_send_msg (SpiceCtrlController* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +gboolean spice_ctrl_controller_send_msg_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error); +static void spice_ctrl_controller_send_msg_data_free (gpointer _data); +static gboolean spice_ctrl_controller_send_msg_co (SpiceCtrlControllerSendMsgData* _data_); +void spice_ctrl_output_stream_write (GOutputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_output_stream_write_finish (GAsyncResult* _res_, GError** error); +static guint8* _vala_array_dup1 (guint8* self, int length); +static void spice_ctrl_controller_send_msg_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +static guint8* _vala_array_dup2 (guint8* self, int length); +static gboolean spice_ctrl_controller_handle_message (SpiceCtrlController* self, ControllerMsg* msg); +static void spice_ctrl_controller_set_host (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_port (SpiceCtrlController* self, guint32 value); +guint32 spice_ctrl_controller_get_port (SpiceCtrlController* self); +static void spice_ctrl_controller_set_sport (SpiceCtrlController* self, guint32 value); +guint32 spice_ctrl_controller_get_sport (SpiceCtrlController* self); +static void spice_ctrl_controller_set_password (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_secure_channels (SpiceCtrlController* self, gchar** value, int value_length1); +static void spice_ctrl_controller_set_disable_channels (SpiceCtrlController* self, gchar** value, int value_length1); +static void spice_ctrl_controller_set_tls_ciphers (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_ca_file (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_host_subject (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_display_flags (SpiceCtrlController* self, unsigned int value); +static void spice_ctrl_controller_set_title (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_enable_smartcard (SpiceCtrlController* self, gboolean value); +SpiceCtrlMenu* spice_ctrl_menu_new_from_string (const gchar* str); +SpiceCtrlMenu* spice_ctrl_menu_construct_from_string (GType object_type, const gchar* str); +static void spice_ctrl_controller_set_menu (SpiceCtrlController* self, SpiceCtrlMenu* value); +static void spice_ctrl_controller_set_send_cad (SpiceCtrlController* self, gboolean value); +static void spice_ctrl_controller_set_hotkeys (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_color_depth (SpiceCtrlController* self, guint32 value); +static void spice_ctrl_controller_set_disable_effects (SpiceCtrlController* self, gchar** value, int value_length1); +static void spice_ctrl_controller_set_enable_usbredir (SpiceCtrlController* self, gboolean value); +static void spice_ctrl_controller_set_enable_usb_autoshare (SpiceCtrlController* self, gboolean value); +static void spice_ctrl_controller_set_usb_filter (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_set_proxy (SpiceCtrlController* self, const gchar* value); +static void spice_ctrl_controller_handle_client_data_free (gpointer _data); +static void spice_ctrl_controller_handle_client (SpiceCtrlController* self, GIOStream* c, GAsyncReadyCallback _callback_, gpointer _user_data_); +static void spice_ctrl_controller_handle_client_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_controller_handle_client_co (SpiceCtrlControllerHandleClientData* _data_); +void spice_ctrl_input_stream_read (GInputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_input_stream_read_finish (GAsyncResult* _res_, GError** error); +static void spice_ctrl_controller_handle_client_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +SpiceCtrlController* spice_ctrl_controller_new (void); +SpiceCtrlController* spice_ctrl_controller_construct (GType object_type); +static void spice_ctrl_controller_listen_data_free (gpointer _data); +void spice_ctrl_controller_listen (SpiceCtrlController* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_controller_listen_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_controller_listen_co (SpiceCtrlControllerListenData* _data_); +static void spice_ctrl_controller_listen_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +const gchar* spice_ctrl_controller_get_host (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_password (SpiceCtrlController* self); +unsigned int spice_ctrl_controller_get_display_flags (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_tls_ciphers (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_host_subject (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_ca_file (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_title (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_hotkeys (SpiceCtrlController* self); +gchar** spice_ctrl_controller_get_secure_channels (SpiceCtrlController* self, int* result_length1); +static gchar** _vala_array_dup3 (gchar** self, int length); +gchar** spice_ctrl_controller_get_disable_channels (SpiceCtrlController* self, int* result_length1); +static gchar** _vala_array_dup4 (gchar** self, int length); +SpiceCtrlMenu* spice_ctrl_controller_get_menu (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_smartcard (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_send_cad (SpiceCtrlController* self); +gchar** spice_ctrl_controller_get_disable_effects (SpiceCtrlController* self, int* result_length1); +static gchar** _vala_array_dup5 (gchar** self, int length); +guint32 spice_ctrl_controller_get_color_depth (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_usbredir (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_usb_autoshare (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_usb_filter (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_proxy (SpiceCtrlController* self); +static void spice_ctrl_controller_finalize (GObject* obj); +static void _vala_spice_ctrl_controller_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); +static void _vala_spice_ctrl_controller_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); +static gint _vala_array_length (gpointer array); + + +GQuark spice_ctrl_error_quark (void) { + return g_quark_from_static_string ("spice_ctrl_error-quark"); +} + + +static void _g_object_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (g_object_unref (var), NULL)); +} + + +static void _g_list_free__g_object_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _g_object_unref0_, NULL); + g_list_free (self); +} + + +void spice_ctrl_controller_menu_item_click_msg (SpiceCtrlController* self, gint32 item_id) { + ControllerValue msg = {0}; + gint32 _tmp0_ = 0; + guint8* p = NULL; + ControllerValue _tmp1_ = {0}; + ControllerMsg _tmp2_ = {0}; + guint32 _tmp3_ = 0U; + gint p_length1 = 0; + gint _p_size_ = 0; + g_return_if_fail (self != NULL); + memset (&msg, 0, sizeof (ControllerValue)); + msg.base.size = (guint32) sizeof (ControllerValue); + msg.base.id = (guint32) CONTROLLER_MENU_ITEM_CLICK; + _tmp0_ = item_id; + msg.value = (guint32) _tmp0_; + _tmp1_ = msg; + _tmp2_ = _tmp1_.base; + _tmp3_ = _tmp2_.size; + p = ((guint8*) (&msg)) + 0; + p_length1 = ((gint) _tmp3_) - 0; + _p_size_ = p_length1; + spice_ctrl_controller_send_msg (self, p, p_length1, NULL, NULL); +} + + +static void spice_ctrl_controller_send_msg_data_free (gpointer _data) { + SpiceCtrlControllerSendMsgData* _data_; + _data_ = _data; + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlControllerSendMsgData, _data_); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +void spice_ctrl_controller_send_msg (SpiceCtrlController* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlControllerSendMsgData* _data_; + SpiceCtrlController* _tmp0_ = NULL; + guint8* _tmp1_ = NULL; + gint _tmp1__length1 = 0; + _data_ = g_slice_new0 (SpiceCtrlControllerSendMsgData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_controller_send_msg); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_controller_send_msg_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _tmp1_ = p; + _tmp1__length1 = p_length1; + _data_->p = _tmp1_; + _data_->p_length1 = _tmp1__length1; + spice_ctrl_controller_send_msg_co (_data_); +} + + +gboolean spice_ctrl_controller_send_msg_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error) { + gboolean result; + SpiceCtrlControllerSendMsgData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return FALSE; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); + result = _data_->result; + return result; +} + + +static guint8* _vala_array_dup1 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static void spice_ctrl_controller_send_msg_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlControllerSendMsgData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_controller_send_msg_co (_data_); +} + + +static guint8* _vala_array_dup2 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static gboolean spice_ctrl_controller_send_msg_co (SpiceCtrlControllerSendMsgData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + case 2: + goto _state_2; + default: + g_assert_not_reached (); + } + _state_0: + { + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = _data_->self->priv->excl_connection; + if (_data_->_tmp0_ != NULL) { + _data_->_tmp1_ = NULL; + _data_->_tmp1_ = _data_->self->priv->excl_connection; + _data_->_tmp2_ = NULL; + _data_->_tmp2_ = g_io_stream_get_output_stream (_data_->_tmp1_); + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = _data_->_tmp2_; + _data_->_tmp4_ = NULL; + _data_->_tmp4__length1 = 0; + _data_->_tmp4_ = _data_->p; + _data_->_tmp4__length1 = _data_->p_length1; + _data_->_tmp5_ = NULL; + _data_->_tmp5__length1 = 0; + _data_->_tmp5_ = (_data_->_tmp4_ != NULL) ? _vala_array_dup1 (_data_->_tmp4_, _data_->_tmp4__length1) : ((gpointer) _data_->_tmp4_); + _data_->_tmp5__length1 = _data_->_tmp4__length1; + _data_->_state_ = 1; + spice_ctrl_output_stream_write (_data_->_tmp3_, _data_->_tmp5_, _data_->_tmp5__length1, spice_ctrl_controller_send_msg_ready, _data_); + return FALSE; + _state_1: + spice_ctrl_output_stream_write_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + goto __catch1_g_error; + } + } else { + _data_->_tmp6_ = NULL; + _data_->_tmp6_ = _data_->self->priv->clients; + { + _data_->c_collection = _data_->_tmp6_; + for (_data_->c_it = _data_->c_collection; _data_->c_it != NULL; _data_->c_it = _data_->c_it->next) { + _data_->_tmp7_ = NULL; + _data_->_tmp7_ = _g_object_ref0 ((GIOStream*) _data_->c_it->data); + _data_->c = _data_->_tmp7_; + { + _data_->_tmp8_ = NULL; + _data_->_tmp8_ = _data_->c; + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = g_io_stream_get_output_stream (_data_->_tmp8_); + _data_->_tmp10_ = NULL; + _data_->_tmp10_ = _data_->_tmp9_; + _data_->_tmp11_ = NULL; + _data_->_tmp11__length1 = 0; + _data_->_tmp11_ = _data_->p; + _data_->_tmp11__length1 = _data_->p_length1; + _data_->_tmp12_ = NULL; + _data_->_tmp12__length1 = 0; + _data_->_tmp12_ = (_data_->_tmp11_ != NULL) ? _vala_array_dup2 (_data_->_tmp11_, _data_->_tmp11__length1) : ((gpointer) _data_->_tmp11_); + _data_->_tmp12__length1 = _data_->_tmp11__length1; + _data_->_state_ = 2; + spice_ctrl_output_stream_write (_data_->_tmp10_, _data_->_tmp12_, _data_->_tmp12__length1, spice_ctrl_controller_send_msg_ready, _data_); + return FALSE; + _state_2: + spice_ctrl_output_stream_write_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + _g_object_unref0 (_data_->c); + goto __catch1_g_error; + } + _g_object_unref0 (_data_->c); + } + } + } + } + } + goto __finally1; + __catch1_g_error: + { + _data_->e = _data_->_inner_error_; + _data_->_inner_error_ = NULL; + _data_->_tmp13_ = NULL; + _data_->_tmp13_ = _data_->e; + _data_->_tmp14_ = NULL; + _data_->_tmp14_ = _data_->_tmp13_->message; + g_warning ("controller.vala:79: %s", _data_->_tmp14_); + _g_error_free0 (_data_->e); + } + __finally1: + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->result = TRUE; + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +static gboolean spice_ctrl_controller_handle_message (SpiceCtrlController* self, ControllerMsg* msg) { + gboolean result = FALSE; + ControllerValue* v = NULL; + ControllerMsg* _tmp0_ = NULL; + ControllerData* d = NULL; + ControllerMsg* _tmp1_ = NULL; + const gchar* str = NULL; + ControllerMsg* _tmp2_ = NULL; + guint32 _tmp3_ = 0U; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = msg; + v = (ControllerValue*) _tmp0_; + _tmp1_ = msg; + d = (ControllerData*) _tmp1_; + str = (const gchar*) (&(*d).data); + _tmp2_ = msg; + _tmp3_ = (*_tmp2_).id; + switch (_tmp3_) { + case CONTROLLER_HOST: + { + const gchar* _tmp4_ = NULL; + const gchar* _tmp5_ = NULL; + gchar* _tmp6_ = NULL; + gchar* _tmp7_ = NULL; + _tmp4_ = str; + spice_ctrl_controller_set_host (self, _tmp4_); + _tmp5_ = str; + _tmp6_ = g_strdup_printf ("got HOST: %s", _tmp5_); + _tmp7_ = _tmp6_; + g_debug ("controller.vala:97: %s", _tmp7_); + _g_free0 (_tmp7_); + break; + } + case CONTROLLER_PORT: + { + ControllerValue* _tmp8_ = NULL; + guint32 _tmp9_ = 0U; + guint32 _tmp10_ = 0U; + gchar* _tmp11_ = NULL; + gchar* _tmp12_ = NULL; + _tmp8_ = v; + _tmp9_ = (*_tmp8_).value; + spice_ctrl_controller_set_port (self, _tmp9_); + _tmp10_ = self->priv->_port; + _tmp11_ = g_strdup_printf ("got PORT: %u", (guint) _tmp10_); + _tmp12_ = _tmp11_; + g_debug ("controller.vala:101: %s", _tmp12_); + _g_free0 (_tmp12_); + break; + } + case CONTROLLER_SPORT: + { + ControllerValue* _tmp13_ = NULL; + guint32 _tmp14_ = 0U; + guint32 _tmp15_ = 0U; + gchar* _tmp16_ = NULL; + gchar* _tmp17_ = NULL; + _tmp13_ = v; + _tmp14_ = (*_tmp13_).value; + spice_ctrl_controller_set_sport (self, _tmp14_); + _tmp15_ = self->priv->_sport; + _tmp16_ = g_strdup_printf ("got SPORT: %u", (guint) _tmp15_); + _tmp17_ = _tmp16_; + g_debug ("controller.vala:105: %s", _tmp17_); + _g_free0 (_tmp17_); + break; + } + case CONTROLLER_PASSWORD: + { + const gchar* _tmp18_ = NULL; + _tmp18_ = str; + spice_ctrl_controller_set_password (self, _tmp18_); + g_debug ("controller.vala:109: got PASSWORD"); + break; + } + case CONTROLLER_SECURE_CHANNELS: + { + const gchar* _tmp19_ = NULL; + gchar** _tmp20_ = NULL; + gchar** _tmp21_ = NULL; + gchar** _tmp22_ = NULL; + gint _tmp22__length1 = 0; + const gchar* _tmp23_ = NULL; + gchar* _tmp24_ = NULL; + gchar* _tmp25_ = NULL; + _tmp19_ = str; + _tmp21_ = _tmp20_ = g_strsplit (_tmp19_, ",", 0); + _tmp22_ = _tmp21_; + _tmp22__length1 = _vala_array_length (_tmp20_); + spice_ctrl_controller_set_secure_channels (self, _tmp22_, _vala_array_length (_tmp20_)); + _tmp22_ = (_vala_array_free (_tmp22_, _tmp22__length1, (GDestroyNotify) g_free), NULL); + _tmp23_ = str; + _tmp24_ = g_strdup_printf ("got SECURE_CHANNELS %s", _tmp23_); + _tmp25_ = _tmp24_; + g_debug ("controller.vala:114: %s", _tmp25_); + _g_free0 (_tmp25_); + break; + } + case CONTROLLER_DISABLE_CHANNELS: + { + const gchar* _tmp26_ = NULL; + gchar** _tmp27_ = NULL; + gchar** _tmp28_ = NULL; + gchar** _tmp29_ = NULL; + gint _tmp29__length1 = 0; + const gchar* _tmp30_ = NULL; + gchar* _tmp31_ = NULL; + gchar* _tmp32_ = NULL; + _tmp26_ = str; + _tmp28_ = _tmp27_ = g_strsplit (_tmp26_, ",", 0); + _tmp29_ = _tmp28_; + _tmp29__length1 = _vala_array_length (_tmp27_); + spice_ctrl_controller_set_disable_channels (self, _tmp29_, _vala_array_length (_tmp27_)); + _tmp29_ = (_vala_array_free (_tmp29_, _tmp29__length1, (GDestroyNotify) g_free), NULL); + _tmp30_ = str; + _tmp31_ = g_strdup_printf ("got DISABLE_CHANNELS %s", _tmp30_); + _tmp32_ = _tmp31_; + g_debug ("controller.vala:119: %s", _tmp32_); + _g_free0 (_tmp32_); + break; + } + case CONTROLLER_TLS_CIPHERS: + { + const gchar* _tmp33_ = NULL; + const gchar* _tmp34_ = NULL; + gchar* _tmp35_ = NULL; + gchar* _tmp36_ = NULL; + _tmp33_ = str; + spice_ctrl_controller_set_tls_ciphers (self, _tmp33_); + _tmp34_ = str; + _tmp35_ = g_strdup_printf ("got TLS_CIPHERS %s", _tmp34_); + _tmp36_ = _tmp35_; + g_debug ("controller.vala:124: %s", _tmp36_); + _g_free0 (_tmp36_); + break; + } + case CONTROLLER_CA_FILE: + { + const gchar* _tmp37_ = NULL; + const gchar* _tmp38_ = NULL; + gchar* _tmp39_ = NULL; + gchar* _tmp40_ = NULL; + _tmp37_ = str; + spice_ctrl_controller_set_ca_file (self, _tmp37_); + _tmp38_ = str; + _tmp39_ = g_strdup_printf ("got CA_FILE %s", _tmp38_); + _tmp40_ = _tmp39_; + g_debug ("controller.vala:128: %s", _tmp40_); + _g_free0 (_tmp40_); + break; + } + case CONTROLLER_HOST_SUBJECT: + { + const gchar* _tmp41_ = NULL; + const gchar* _tmp42_ = NULL; + gchar* _tmp43_ = NULL; + gchar* _tmp44_ = NULL; + _tmp41_ = str; + spice_ctrl_controller_set_host_subject (self, _tmp41_); + _tmp42_ = str; + _tmp43_ = g_strdup_printf ("got HOST_SUBJECT %s", _tmp42_); + _tmp44_ = _tmp43_; + g_debug ("controller.vala:132: %s", _tmp44_); + _g_free0 (_tmp44_); + break; + } + case CONTROLLER_FULL_SCREEN: + { + ControllerValue* _tmp45_ = NULL; + guint32 _tmp46_ = 0U; + ControllerValue* _tmp47_ = NULL; + guint32 _tmp48_ = 0U; + gchar* _tmp49_ = NULL; + gchar* _tmp50_ = NULL; + _tmp45_ = v; + _tmp46_ = (*_tmp45_).value; + spice_ctrl_controller_set_display_flags (self, (unsigned int) _tmp46_); + _tmp47_ = v; + _tmp48_ = (*_tmp47_).value; + _tmp49_ = g_strdup_printf ("got FULL_SCREEN 0x%x", (guint) _tmp48_); + _tmp50_ = _tmp49_; + g_debug ("controller.vala:137: %s", _tmp50_); + _g_free0 (_tmp50_); + break; + } + case CONTROLLER_SET_TITLE: + { + const gchar* _tmp51_ = NULL; + const gchar* _tmp52_ = NULL; + gchar* _tmp53_ = NULL; + gchar* _tmp54_ = NULL; + _tmp51_ = str; + spice_ctrl_controller_set_title (self, _tmp51_); + _tmp52_ = str; + _tmp53_ = g_strdup_printf ("got TITLE %s", _tmp52_); + _tmp54_ = _tmp53_; + g_debug ("controller.vala:141: %s", _tmp54_); + _g_free0 (_tmp54_); + break; + } + case CONTROLLER_ENABLE_SMARTCARD: + { + ControllerValue* _tmp55_ = NULL; + guint32 _tmp56_ = 0U; + ControllerValue* _tmp57_ = NULL; + guint32 _tmp58_ = 0U; + gchar* _tmp59_ = NULL; + gchar* _tmp60_ = NULL; + _tmp55_ = v; + _tmp56_ = (*_tmp55_).value; + spice_ctrl_controller_set_enable_smartcard (self, (gboolean) _tmp56_); + _tmp57_ = v; + _tmp58_ = (*_tmp57_).value; + _tmp59_ = g_strdup_printf ("got ENABLE_SMARTCARD 0x%x", (guint) _tmp58_); + _tmp60_ = _tmp59_; + g_debug ("controller.vala:145: %s", _tmp60_); + _g_free0 (_tmp60_); + break; + } + case CONTROLLER_CREATE_MENU: + { + const gchar* _tmp61_ = NULL; + SpiceCtrlMenu* _tmp62_ = NULL; + SpiceCtrlMenu* _tmp63_ = NULL; + const gchar* _tmp64_ = NULL; + gchar* _tmp65_ = NULL; + gchar* _tmp66_ = NULL; + _tmp61_ = str; + _tmp62_ = spice_ctrl_menu_new_from_string (_tmp61_); + _tmp63_ = _tmp62_; + spice_ctrl_controller_set_menu (self, _tmp63_); + _g_object_unref0 (_tmp63_); + _tmp64_ = str; + _tmp65_ = g_strdup_printf ("got CREATE_MENU %s", _tmp64_); + _tmp66_ = _tmp65_; + g_debug ("controller.vala:150: %s", _tmp66_); + _g_free0 (_tmp66_); + break; + } + case CONTROLLER_DELETE_MENU: + { + spice_ctrl_controller_set_menu (self, NULL); + g_debug ("controller.vala:154: got DELETE_MENU request"); + break; + } + case CONTROLLER_SEND_CAD: + { + ControllerValue* _tmp67_ = NULL; + guint32 _tmp68_ = 0U; + ControllerValue* _tmp69_ = NULL; + guint32 _tmp70_ = 0U; + gchar* _tmp71_ = NULL; + gchar* _tmp72_ = NULL; + _tmp67_ = v; + _tmp68_ = (*_tmp67_).value; + spice_ctrl_controller_set_send_cad (self, (gboolean) _tmp68_); + _tmp69_ = v; + _tmp70_ = (*_tmp69_).value; + _tmp71_ = g_strdup_printf ("got SEND_CAD %u", (guint) _tmp70_); + _tmp72_ = _tmp71_; + g_debug ("controller.vala:159: %s", _tmp72_); + _g_free0 (_tmp72_); + break; + } + case CONTROLLER_HOTKEYS: + { + const gchar* _tmp73_ = NULL; + const gchar* _tmp74_ = NULL; + gchar* _tmp75_ = NULL; + gchar* _tmp76_ = NULL; + _tmp73_ = str; + spice_ctrl_controller_set_hotkeys (self, _tmp73_); + _tmp74_ = str; + _tmp75_ = g_strdup_printf ("got HOTKEYS %s", _tmp74_); + _tmp76_ = _tmp75_; + g_debug ("controller.vala:164: %s", _tmp76_); + _g_free0 (_tmp76_); + break; + } + case CONTROLLER_COLOR_DEPTH: + { + ControllerValue* _tmp77_ = NULL; + guint32 _tmp78_ = 0U; + ControllerValue* _tmp79_ = NULL; + guint32 _tmp80_ = 0U; + gchar* _tmp81_ = NULL; + gchar* _tmp82_ = NULL; + _tmp77_ = v; + _tmp78_ = (*_tmp77_).value; + spice_ctrl_controller_set_color_depth (self, _tmp78_); + _tmp79_ = v; + _tmp80_ = (*_tmp79_).value; + _tmp81_ = g_strdup_printf ("got COLOR_DEPTH %u", (guint) _tmp80_); + _tmp82_ = _tmp81_; + g_debug ("controller.vala:169: %s", _tmp82_); + _g_free0 (_tmp82_); + break; + } + case CONTROLLER_DISABLE_EFFECTS: + { + const gchar* _tmp83_ = NULL; + gchar** _tmp84_ = NULL; + gchar** _tmp85_ = NULL; + gchar** _tmp86_ = NULL; + gint _tmp86__length1 = 0; + const gchar* _tmp87_ = NULL; + gchar* _tmp88_ = NULL; + gchar* _tmp89_ = NULL; + _tmp83_ = str; + _tmp85_ = _tmp84_ = g_strsplit (_tmp83_, ",", 0); + _tmp86_ = _tmp85_; + _tmp86__length1 = _vala_array_length (_tmp84_); + spice_ctrl_controller_set_disable_effects (self, _tmp86_, _vala_array_length (_tmp84_)); + _tmp86_ = (_vala_array_free (_tmp86_, _tmp86__length1, (GDestroyNotify) g_free), NULL); + _tmp87_ = str; + _tmp88_ = g_strdup_printf ("got DISABLE_EFFECTS %s", _tmp87_); + _tmp89_ = _tmp88_; + g_debug ("controller.vala:173: %s", _tmp89_); + _g_free0 (_tmp89_); + break; + } + case CONTROLLER_CONNECT: + { + g_signal_emit_by_name (self, "do-connect"); + g_debug ("controller.vala:178: got CONNECT request"); + break; + } + case CONTROLLER_SHOW: + { + g_signal_emit_by_name (self, "show"); + g_debug ("controller.vala:182: got SHOW request"); + break; + } + case CONTROLLER_HIDE: + { + g_signal_emit_by_name (self, "hide"); + g_debug ("controller.vala:186: got HIDE request"); + break; + } + case CONTROLLER_ENABLE_USB: + { + ControllerValue* _tmp90_ = NULL; + guint32 _tmp91_ = 0U; + ControllerValue* _tmp92_ = NULL; + guint32 _tmp93_ = 0U; + gchar* _tmp94_ = NULL; + gchar* _tmp95_ = NULL; + _tmp90_ = v; + _tmp91_ = (*_tmp90_).value; + spice_ctrl_controller_set_enable_usbredir (self, (gboolean) _tmp91_); + _tmp92_ = v; + _tmp93_ = (*_tmp92_).value; + _tmp94_ = g_strdup_printf ("got ENABLE_USB %u", (guint) _tmp93_); + _tmp95_ = _tmp94_; + g_debug ("controller.vala:190: %s", _tmp95_); + _g_free0 (_tmp95_); + break; + } + case CONTROLLER_ENABLE_USB_AUTOSHARE: + { + ControllerValue* _tmp96_ = NULL; + guint32 _tmp97_ = 0U; + ControllerValue* _tmp98_ = NULL; + guint32 _tmp99_ = 0U; + gchar* _tmp100_ = NULL; + gchar* _tmp101_ = NULL; + _tmp96_ = v; + _tmp97_ = (*_tmp96_).value; + spice_ctrl_controller_set_enable_usb_autoshare (self, (gboolean) _tmp97_); + _tmp98_ = v; + _tmp99_ = (*_tmp98_).value; + _tmp100_ = g_strdup_printf ("got ENABLE_USB_AUTOSHARE %u", (guint) _tmp99_); + _tmp101_ = _tmp100_; + g_debug ("controller.vala:194: %s", _tmp101_); + _g_free0 (_tmp101_); + break; + } + case CONTROLLER_USB_FILTER: + { + const gchar* _tmp102_ = NULL; + const gchar* _tmp103_ = NULL; + gchar* _tmp104_ = NULL; + gchar* _tmp105_ = NULL; + _tmp102_ = str; + spice_ctrl_controller_set_usb_filter (self, _tmp102_); + _tmp103_ = str; + _tmp104_ = g_strdup_printf ("got USB_FILTER %s", _tmp103_); + _tmp105_ = _tmp104_; + g_debug ("controller.vala:198: %s", _tmp105_); + _g_free0 (_tmp105_); + break; + } + case CONTROLLER_PROXY: + { + const gchar* _tmp106_ = NULL; + const gchar* _tmp107_ = NULL; + gchar* _tmp108_ = NULL; + gchar* _tmp109_ = NULL; + _tmp106_ = str; + spice_ctrl_controller_set_proxy (self, _tmp106_); + _tmp107_ = str; + _tmp108_ = g_strdup_printf ("got PROXY %s", _tmp107_); + _tmp109_ = _tmp108_; + g_debug ("controller.vala:202: %s", _tmp109_); + _g_free0 (_tmp109_); + break; + } + default: + { + ControllerMsg* _tmp110_ = NULL; + guint32 _tmp111_ = 0U; + gchar* _tmp112_ = NULL; + gchar* _tmp113_ = NULL; + _tmp110_ = msg; + _tmp111_ = (*_tmp110_).id; + _tmp112_ = g_strdup_printf ("got unknown msg.id %u", (guint) _tmp111_); + _tmp113_ = _tmp112_; + g_debug ("controller.vala:205: %s", _tmp113_); + _g_free0 (_tmp113_); + g_warn_if_reached (); + result = FALSE; + return result; + } + } + result = TRUE; + return result; +} + + +static void spice_ctrl_controller_handle_client_data_free (gpointer _data) { + SpiceCtrlControllerHandleClientData* _data_; + _data_ = _data; + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlControllerHandleClientData, _data_); +} + + +static void spice_ctrl_controller_handle_client (SpiceCtrlController* self, GIOStream* c, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlControllerHandleClientData* _data_; + SpiceCtrlController* _tmp0_ = NULL; + GIOStream* _tmp1_ = NULL; + GIOStream* _tmp2_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlControllerHandleClientData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_controller_handle_client); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_controller_handle_client_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _tmp1_ = c; + _tmp2_ = _g_object_ref0 (_tmp1_); + _g_object_unref0 (_data_->c); + _data_->c = _tmp2_; + spice_ctrl_controller_handle_client_co (_data_); +} + + +static void spice_ctrl_controller_handle_client_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error) { + SpiceCtrlControllerHandleClientData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_controller_handle_client_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlControllerHandleClientData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_controller_handle_client_co (_data_); +} + + +static gboolean spice_ctrl_controller_handle_client_co (SpiceCtrlControllerHandleClientData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + case 2: + goto _state_2; + case 3: + goto _state_3; + default: + g_assert_not_reached (); + } + _state_0: + _data_->excl = FALSE; + g_debug ("controller.vala:215: new socket client, reading init header"); + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = g_new0 (guint8, sizeof (ControllerInit)); + _data_->p_length1 = 0; + _data_->_p_size_ = 0; + _data_->p = _data_->_tmp0_; + _data_->p_length1 = sizeof (ControllerInit); + _data_->_p_size_ = _data_->p_length1; + _data_->_tmp1_ = NULL; + _data_->_tmp1__length1 = 0; + _data_->_tmp1_ = _data_->p; + _data_->_tmp1__length1 = _data_->p_length1; + _data_->init = (ControllerInit*) _data_->_tmp1_; + _data_->_tmp2_ = NULL; + _data_->_tmp2_ = _data_->c; + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = g_io_stream_get_input_stream (_data_->_tmp2_); + _data_->_tmp4_ = NULL; + _data_->_tmp4_ = _data_->_tmp3_; + _data_->_tmp5_ = NULL; + _data_->_tmp5__length1 = 0; + _data_->_tmp5_ = _data_->p; + _data_->_tmp5__length1 = _data_->p_length1; + _data_->_state_ = 1; + spice_ctrl_input_stream_read (_data_->_tmp4_, _data_->_tmp5_, _data_->_tmp5__length1, spice_ctrl_controller_handle_client_ready, _data_); + return FALSE; + _state_1: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp6_ = NULL; + _data_->_tmp6_ = _data_->init; + memset (&_data_->_tmp7_, 0, sizeof (ControllerInitHeader)); + _data_->_tmp7_ = (*_data_->_tmp6_).base; + _data_->_tmp8_ = 0U; + _data_->_tmp8_ = _data_->_tmp7_.magic; + _data_->_tmp9_ = FALSE; + _data_->_tmp9_ = g_warn_if (_data_->_tmp8_ != CONTROLLER_MAGIC); + if (_data_->_tmp9_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp10_ = NULL; + _data_->_tmp10_ = _data_->init; + memset (&_data_->_tmp11_, 0, sizeof (ControllerInitHeader)); + _data_->_tmp11_ = (*_data_->_tmp10_).base; + _data_->_tmp12_ = 0U; + _data_->_tmp12_ = _data_->_tmp11_.version; + _data_->_tmp13_ = FALSE; + _data_->_tmp13_ = g_warn_if (_data_->_tmp12_ != ((guint32) CONTROLLER_VERSION)); + if (_data_->_tmp13_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp14_ = NULL; + _data_->_tmp14_ = _data_->init; + memset (&_data_->_tmp15_, 0, sizeof (ControllerInitHeader)); + _data_->_tmp15_ = (*_data_->_tmp14_).base; + _data_->_tmp16_ = 0U; + _data_->_tmp16_ = _data_->_tmp15_.size; + _data_->_tmp17_ = FALSE; + _data_->_tmp17_ = g_warn_if (((gulong) _data_->_tmp16_) < sizeof (ControllerInit)); + if (_data_->_tmp17_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp18_ = NULL; + _data_->_tmp18_ = _data_->init; + _data_->_tmp19_ = 0ULL; + _data_->_tmp19_ = (*_data_->_tmp18_).credentials; + _data_->_tmp20_ = FALSE; + _data_->_tmp20_ = g_warn_if (_data_->_tmp19_ != ((guint64) 0)); + if (_data_->_tmp20_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp21_ = NULL; + _data_->_tmp21_ = _data_->self->priv->excl_connection; + _data_->_tmp22_ = FALSE; + _data_->_tmp22_ = g_warn_if (_data_->_tmp21_ != NULL); + if (_data_->_tmp22_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp23_ = NULL; + _data_->_tmp23_ = _data_->init; + _data_->_tmp24_ = 0U; + _data_->_tmp24_ = (*_data_->_tmp23_).flags; + _data_->excl = (gboolean) (_data_->_tmp24_ & CONTROLLER_FLAG_EXCLUSIVE); + _data_->_tmp25_ = FALSE; + _data_->_tmp25_ = _data_->excl; + if (_data_->_tmp25_) { + _data_->_tmp26_ = 0; + _data_->_tmp26_ = _data_->self->priv->nclients; + if (_data_->_tmp26_ > 1) { + _data_->_tmp27_ = 0; + _data_->_tmp27_ = _data_->self->priv->nclients; + _data_->_tmp28_ = NULL; + _data_->_tmp28_ = g_strdup_printf ("%i", _data_->_tmp27_); + _data_->_tmp29_ = NULL; + _data_->_tmp29_ = _data_->_tmp28_; + _data_->_tmp30_ = NULL; + _data_->_tmp30_ = g_strconcat ("Can't make the client exclusive, there is already ", _data_->_tmp29_, " connected clients", NULL); + _data_->_tmp31_ = NULL; + _data_->_tmp31_ = _data_->_tmp30_; + g_warning ("controller.vala:234: %s", _data_->_tmp31_); + _g_free0 (_data_->_tmp31_); + _g_free0 (_data_->_tmp29_); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp32_ = NULL; + _data_->_tmp32_ = _data_->c; + _data_->_tmp33_ = NULL; + _data_->_tmp33_ = _g_object_ref0 (_data_->_tmp32_); + _g_object_unref0 (_data_->self->priv->excl_connection); + _data_->self->priv->excl_connection = _data_->_tmp33_; + } + g_signal_emit_by_name (_data_->self, "client-connected"); + { + _data_->_tmp34_ = TRUE; + while (TRUE) { + if (!_data_->_tmp34_) { + } + _data_->_tmp34_ = FALSE; + _data_->_tmp35_ = NULL; + _data_->_tmp35_ = g_new0 (guint8, sizeof (ControllerMsg)); + _data_->t_length1 = 0; + _data_->_t_size_ = 0; + _data_->t = _data_->_tmp35_; + _data_->t_length1 = sizeof (ControllerMsg); + _data_->_t_size_ = _data_->t_length1; + _data_->_tmp36_ = NULL; + _data_->_tmp36_ = _data_->c; + _data_->_tmp37_ = NULL; + _data_->_tmp37_ = g_io_stream_get_input_stream (_data_->_tmp36_); + _data_->_tmp38_ = NULL; + _data_->_tmp38_ = _data_->_tmp37_; + _data_->_tmp39_ = NULL; + _data_->_tmp39__length1 = 0; + _data_->_tmp39_ = _data_->t; + _data_->_tmp39__length1 = _data_->t_length1; + _data_->_state_ = 2; + spice_ctrl_input_stream_read (_data_->_tmp38_, _data_->_tmp39_, _data_->_tmp39__length1, spice_ctrl_controller_handle_client_ready, _data_); + return FALSE; + _state_2: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->t = (g_free (_data_->t), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp40_ = NULL; + _data_->_tmp40__length1 = 0; + _data_->_tmp40_ = _data_->t; + _data_->_tmp40__length1 = _data_->t_length1; + _data_->msg = (ControllerMsg*) _data_->_tmp40_; + _data_->_tmp41_ = NULL; + _data_->_tmp41_ = _data_->msg; + _data_->_tmp42_ = 0U; + _data_->_tmp42_ = (*_data_->_tmp41_).id; + _data_->_tmp43_ = NULL; + _data_->_tmp43_ = g_strdup_printf ("%u", _data_->_tmp42_); + _data_->_tmp44_ = NULL; + _data_->_tmp44_ = _data_->_tmp43_; + _data_->_tmp45_ = NULL; + _data_->_tmp45_ = g_strconcat ("new message ", _data_->_tmp44_, NULL); + _data_->_tmp46_ = NULL; + _data_->_tmp46_ = _data_->_tmp45_; + _data_->_tmp47_ = NULL; + _data_->_tmp47_ = g_strconcat (_data_->_tmp46_, "size ", NULL); + _data_->_tmp48_ = NULL; + _data_->_tmp48_ = _data_->_tmp47_; + _data_->_tmp49_ = NULL; + _data_->_tmp49_ = _data_->msg; + _data_->_tmp50_ = 0U; + _data_->_tmp50_ = (*_data_->_tmp49_).size; + _data_->_tmp51_ = NULL; + _data_->_tmp51_ = g_strdup_printf ("%u", _data_->_tmp50_); + _data_->_tmp52_ = NULL; + _data_->_tmp52_ = _data_->_tmp51_; + _data_->_tmp53_ = NULL; + _data_->_tmp53_ = g_strconcat (_data_->_tmp48_, _data_->_tmp52_, NULL); + _data_->_tmp54_ = NULL; + _data_->_tmp54_ = _data_->_tmp53_; + g_debug ("controller.vala:246: %s", _data_->_tmp54_); + _g_free0 (_data_->_tmp54_); + _g_free0 (_data_->_tmp52_); + _g_free0 (_data_->_tmp48_); + _g_free0 (_data_->_tmp46_); + _g_free0 (_data_->_tmp44_); + _data_->_tmp55_ = NULL; + _data_->_tmp55_ = _data_->msg; + _data_->_tmp56_ = 0U; + _data_->_tmp56_ = (*_data_->_tmp55_).size; + _data_->_tmp57_ = FALSE; + _data_->_tmp57_ = g_warn_if (((gulong) _data_->_tmp56_) < sizeof (ControllerMsg)); + if (_data_->_tmp57_) { + _data_->t = (g_free (_data_->t), NULL); + break; + } + _data_->_tmp58_ = NULL; + _data_->_tmp58_ = _data_->msg; + _data_->_tmp59_ = 0U; + _data_->_tmp59_ = (*_data_->_tmp58_).size; + if (((gulong) _data_->_tmp59_) > sizeof (ControllerMsg)) { + _data_->_tmp60_ = NULL; + _data_->_tmp60_ = _data_->msg; + _data_->_tmp61_ = 0U; + _data_->_tmp61_ = (*_data_->_tmp60_).size; + _data_->_tmp62_ = 0; + _data_->_tmp62_ = (gint) _data_->_tmp61_; + _data_->t = g_renew (guint8, _data_->t, (gint) _data_->_tmp61_); + (_data_->_tmp62_ > _data_->t_length1) ? memset (_data_->t + _data_->t_length1, 0, sizeof (guint8) * (_data_->_tmp62_ - _data_->t_length1)) : NULL; + _data_->t_length1 = _data_->_tmp62_; + _data_->_t_size_ = _data_->_tmp62_; + _data_->_tmp63_ = NULL; + _data_->_tmp63__length1 = 0; + _data_->_tmp63_ = _data_->t; + _data_->_tmp63__length1 = _data_->t_length1; + _data_->msg = (ControllerMsg*) _data_->_tmp63_; + _data_->_tmp64_ = NULL; + _data_->_tmp64_ = _data_->c; + _data_->_tmp65_ = NULL; + _data_->_tmp65_ = g_io_stream_get_input_stream (_data_->_tmp64_); + _data_->_tmp66_ = NULL; + _data_->_tmp66_ = _data_->_tmp65_; + _data_->_tmp67_ = NULL; + _data_->_tmp67__length1 = 0; + _data_->_tmp67_ = _data_->t; + _data_->_tmp67__length1 = _data_->t_length1; + _data_->_tmp68_ = NULL; + _data_->_tmp68_ = _data_->msg; + _data_->_tmp69_ = 0U; + _data_->_tmp69_ = (*_data_->_tmp68_).size; + _data_->_state_ = 3; + spice_ctrl_input_stream_read (_data_->_tmp66_, _data_->_tmp67_ + ((gint) sizeof (ControllerMsg)), ((gint) _data_->_tmp69_) - ((gint) sizeof (ControllerMsg)), spice_ctrl_controller_handle_client_ready, _data_); + return FALSE; + _state_3: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->t = (g_free (_data_->t), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + } + _data_->_tmp70_ = NULL; + _data_->_tmp70_ = _data_->msg; + spice_ctrl_controller_handle_message (_data_->self, _data_->_tmp70_); + _data_->t = (g_free (_data_->t), NULL); + } + } + _data_->_tmp71_ = FALSE; + _data_->_tmp71_ = _data_->excl; + if (_data_->_tmp71_) { + _g_object_unref0 (_data_->self->priv->excl_connection); + _data_->self->priv->excl_connection = NULL; + } + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +SpiceCtrlController* spice_ctrl_controller_construct (GType object_type) { + SpiceCtrlController * self = NULL; + self = (SpiceCtrlController*) g_object_new (object_type, NULL); + return self; +} + + +SpiceCtrlController* spice_ctrl_controller_new (void) { + return spice_ctrl_controller_construct (SPICE_CTRL_TYPE_CONTROLLER); +} + + +static void spice_ctrl_controller_listen_data_free (gpointer _data) { + SpiceCtrlControllerListenData* _data_; + _data_ = _data; + _g_free0 (_data_->addr); + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlControllerListenData, _data_); +} + + +void spice_ctrl_controller_listen (SpiceCtrlController* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlControllerListenData* _data_; + SpiceCtrlController* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gchar* _tmp2_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlControllerListenData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_controller_listen); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_controller_listen_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _tmp1_ = addr; + _tmp2_ = g_strdup (_tmp1_); + _g_free0 (_data_->addr); + _data_->addr = _tmp2_; + spice_ctrl_controller_listen_co (_data_); +} + + +void spice_ctrl_controller_listen_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error) { + SpiceCtrlControllerListenData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_controller_listen_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlControllerListenData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_controller_listen_co (_data_); +} + + +static gboolean spice_ctrl_controller_listen_co (SpiceCtrlControllerListenData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + case 2: + goto _state_2; + default: + g_assert_not_reached (); + } + _state_0: + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = _data_->addr; + _data_->_tmp1_ = NULL; + _data_->_tmp1_ = spice_controller_listener_new (_data_->_tmp0_, &_data_->_inner_error_); + _data_->listener = _data_->_tmp1_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + { + _data_->_tmp2_ = TRUE; + while (TRUE) { + if (!_data_->_tmp2_) { + } + _data_->_tmp2_ = FALSE; + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = _data_->listener; + _data_->_state_ = 1; + spice_controller_listener_accept_async (_data_->_tmp3_, NULL, spice_ctrl_controller_listen_ready, _data_); + return FALSE; + _state_1: + _data_->_tmp4_ = NULL; + _data_->_tmp4_ = spice_controller_listener_accept_finish (_data_->_tmp3_, _data_->_res_, NULL, &_data_->_inner_error_); + _data_->_tmp5_ = NULL; + _data_->_tmp5_ = _g_object_ref0 (_data_->_tmp4_); + _data_->c = _data_->_tmp5_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp6_ = 0; + _data_->_tmp6_ = _data_->self->priv->nclients; + _data_->self->priv->nclients = _data_->_tmp6_ + 1; + _data_->_tmp7_ = NULL; + _data_->_tmp7_ = _data_->c; + _data_->_tmp8_ = NULL; + _data_->_tmp8_ = _g_object_ref0 (_data_->_tmp7_); + _data_->self->priv->clients = g_list_append (_data_->self->priv->clients, _data_->_tmp8_); + { + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = _data_->c; + _data_->_state_ = 2; + spice_ctrl_controller_handle_client (_data_->self, _data_->_tmp9_, spice_ctrl_controller_listen_ready, _data_); + return FALSE; + _state_2: + spice_ctrl_controller_handle_client_finish (_data_->self, _data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + goto __catch2_g_error; + } + } + goto __finally2; + __catch2_g_error: + { + _data_->e = _data_->_inner_error_; + _data_->_inner_error_ = NULL; + _data_->_tmp10_ = NULL; + _data_->_tmp10_ = _data_->e; + _data_->_tmp11_ = NULL; + _data_->_tmp11_ = _data_->_tmp10_->message; + g_warning ("controller.vala:277: %s", _data_->_tmp11_); + _g_error_free0 (_data_->e); + } + __finally2: + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp12_ = NULL; + _data_->_tmp12_ = _data_->c; + g_io_stream_close (_data_->_tmp12_, NULL, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp13_ = NULL; + _data_->_tmp13_ = _data_->c; + _data_->self->priv->clients = g_list_remove (_data_->self->priv->clients, _data_->_tmp13_); + _data_->_tmp14_ = 0; + _data_->_tmp14_ = _data_->self->priv->nclients; + _data_->self->priv->nclients = _data_->_tmp14_ - 1; + _g_object_unref0 (_data_->c); + } + } + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +const gchar* spice_ctrl_controller_get_host (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_host; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_host (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_host); + self->priv->_host = _tmp1_; + g_object_notify ((GObject *) self, "host"); +} + + +guint32 spice_ctrl_controller_get_port (SpiceCtrlController* self) { + guint32 result; + guint32 _tmp0_ = 0U; + g_return_val_if_fail (self != NULL, 0U); + _tmp0_ = self->priv->_port; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_port (SpiceCtrlController* self, guint32 value) { + guint32 _tmp0_ = 0U; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_port = _tmp0_; + g_object_notify ((GObject *) self, "port"); +} + + +guint32 spice_ctrl_controller_get_sport (SpiceCtrlController* self) { + guint32 result; + guint32 _tmp0_ = 0U; + g_return_val_if_fail (self != NULL, 0U); + _tmp0_ = self->priv->_sport; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_sport (SpiceCtrlController* self, guint32 value) { + guint32 _tmp0_ = 0U; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_sport = _tmp0_; + g_object_notify ((GObject *) self, "sport"); +} + + +const gchar* spice_ctrl_controller_get_password (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_password; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_password (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_password); + self->priv->_password = _tmp1_; + g_object_notify ((GObject *) self, "password"); +} + + +unsigned int spice_ctrl_controller_get_display_flags (SpiceCtrlController* self) { + unsigned int result; + unsigned int _tmp0_ = 0; + g_return_val_if_fail (self != NULL, 0); + _tmp0_ = self->priv->_display_flags; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_display_flags (SpiceCtrlController* self, unsigned int value) { + unsigned int _tmp0_ = 0; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_display_flags = _tmp0_; + g_object_notify ((GObject *) self, "display-flags"); +} + + +const gchar* spice_ctrl_controller_get_tls_ciphers (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_tls_ciphers; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_tls_ciphers (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_tls_ciphers); + self->priv->_tls_ciphers = _tmp1_; + g_object_notify ((GObject *) self, "tls-ciphers"); +} + + +const gchar* spice_ctrl_controller_get_host_subject (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_host_subject; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_host_subject (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_host_subject); + self->priv->_host_subject = _tmp1_; + g_object_notify ((GObject *) self, "host-subject"); +} + + +const gchar* spice_ctrl_controller_get_ca_file (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_ca_file; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_ca_file (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_ca_file); + self->priv->_ca_file = _tmp1_; + g_object_notify ((GObject *) self, "ca-file"); +} + + +const gchar* spice_ctrl_controller_get_title (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_title; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_title (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_title); + self->priv->_title = _tmp1_; + g_object_notify ((GObject *) self, "title"); +} + + +const gchar* spice_ctrl_controller_get_hotkeys (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_hotkeys; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_hotkeys (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_hotkeys); + self->priv->_hotkeys = _tmp1_; + g_object_notify ((GObject *) self, "hotkeys"); +} + + +gchar** spice_ctrl_controller_get_secure_channels (SpiceCtrlController* self, int* result_length1) { + gchar** result; + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_secure_channels; + _tmp0__length1 = self->priv->_secure_channels_length1; + _tmp1_ = _tmp0_; + _tmp1__length1 = _tmp0__length1; + if (result_length1) { + *result_length1 = _tmp1__length1; + } + result = _tmp1_; + return result; +} + + +static gchar** _vala_array_dup3 (gchar** self, int length) { + gchar** result; + int i; + result = g_new0 (gchar*, length + 1); + for (i = 0; i < length; i++) { + gchar* _tmp0_ = NULL; + _tmp0_ = g_strdup (self[i]); + result[i] = _tmp0_; + } + return result; +} + + +static void spice_ctrl_controller_set_secure_channels (SpiceCtrlController* self, gchar** value, int value_length1) { + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp0__length1 = value_length1; + _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup3 (_tmp0_, _tmp0__length1) : ((gpointer) _tmp0_); + _tmp1__length1 = _tmp0__length1; + self->priv->_secure_channels = (_vala_array_free (self->priv->_secure_channels, self->priv->_secure_channels_length1, (GDestroyNotify) g_free), NULL); + self->priv->_secure_channels = _tmp1_; + self->priv->_secure_channels_length1 = _tmp1__length1; + self->priv->__secure_channels_size_ = self->priv->_secure_channels_length1; + g_object_notify ((GObject *) self, "secure-channels"); +} + + +gchar** spice_ctrl_controller_get_disable_channels (SpiceCtrlController* self, int* result_length1) { + gchar** result; + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_disable_channels; + _tmp0__length1 = self->priv->_disable_channels_length1; + _tmp1_ = _tmp0_; + _tmp1__length1 = _tmp0__length1; + if (result_length1) { + *result_length1 = _tmp1__length1; + } + result = _tmp1_; + return result; +} + + +static gchar** _vala_array_dup4 (gchar** self, int length) { + gchar** result; + int i; + result = g_new0 (gchar*, length + 1); + for (i = 0; i < length; i++) { + gchar* _tmp0_ = NULL; + _tmp0_ = g_strdup (self[i]); + result[i] = _tmp0_; + } + return result; +} + + +static void spice_ctrl_controller_set_disable_channels (SpiceCtrlController* self, gchar** value, int value_length1) { + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp0__length1 = value_length1; + _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup4 (_tmp0_, _tmp0__length1) : ((gpointer) _tmp0_); + _tmp1__length1 = _tmp0__length1; + self->priv->_disable_channels = (_vala_array_free (self->priv->_disable_channels, self->priv->_disable_channels_length1, (GDestroyNotify) g_free), NULL); + self->priv->_disable_channels = _tmp1_; + self->priv->_disable_channels_length1 = _tmp1__length1; + self->priv->__disable_channels_size_ = self->priv->_disable_channels_length1; + g_object_notify ((GObject *) self, "disable-channels"); +} + + +SpiceCtrlMenu* spice_ctrl_controller_get_menu (SpiceCtrlController* self) { + SpiceCtrlMenu* result; + SpiceCtrlMenu* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_menu; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_menu (SpiceCtrlController* self, SpiceCtrlMenu* value) { + SpiceCtrlMenu* _tmp0_ = NULL; + SpiceCtrlMenu* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = _g_object_ref0 (_tmp0_); + _g_object_unref0 (self->priv->_menu); + self->priv->_menu = _tmp1_; + g_object_notify ((GObject *) self, "menu"); +} + + +gboolean spice_ctrl_controller_get_enable_smartcard (SpiceCtrlController* self) { + gboolean result; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = self->priv->_enable_smartcard; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_enable_smartcard (SpiceCtrlController* self, gboolean value) { + gboolean _tmp0_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_enable_smartcard = _tmp0_; + g_object_notify ((GObject *) self, "enable-smartcard"); +} + + +gboolean spice_ctrl_controller_get_send_cad (SpiceCtrlController* self) { + gboolean result; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = self->priv->_send_cad; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_send_cad (SpiceCtrlController* self, gboolean value) { + gboolean _tmp0_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_send_cad = _tmp0_; + g_object_notify ((GObject *) self, "send-cad"); +} + + +gchar** spice_ctrl_controller_get_disable_effects (SpiceCtrlController* self, int* result_length1) { + gchar** result; + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_disable_effects; + _tmp0__length1 = self->priv->_disable_effects_length1; + _tmp1_ = _tmp0_; + _tmp1__length1 = _tmp0__length1; + if (result_length1) { + *result_length1 = _tmp1__length1; + } + result = _tmp1_; + return result; +} + + +static gchar** _vala_array_dup5 (gchar** self, int length) { + gchar** result; + int i; + result = g_new0 (gchar*, length + 1); + for (i = 0; i < length; i++) { + gchar* _tmp0_ = NULL; + _tmp0_ = g_strdup (self[i]); + result[i] = _tmp0_; + } + return result; +} + + +static void spice_ctrl_controller_set_disable_effects (SpiceCtrlController* self, gchar** value, int value_length1) { + gchar** _tmp0_ = NULL; + gint _tmp0__length1 = 0; + gchar** _tmp1_ = NULL; + gint _tmp1__length1 = 0; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp0__length1 = value_length1; + _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup5 (_tmp0_, _tmp0__length1) : ((gpointer) _tmp0_); + _tmp1__length1 = _tmp0__length1; + self->priv->_disable_effects = (_vala_array_free (self->priv->_disable_effects, self->priv->_disable_effects_length1, (GDestroyNotify) g_free), NULL); + self->priv->_disable_effects = _tmp1_; + self->priv->_disable_effects_length1 = _tmp1__length1; + self->priv->__disable_effects_size_ = self->priv->_disable_effects_length1; + g_object_notify ((GObject *) self, "disable-effects"); +} + + +guint32 spice_ctrl_controller_get_color_depth (SpiceCtrlController* self) { + guint32 result; + guint32 _tmp0_ = 0U; + g_return_val_if_fail (self != NULL, 0U); + _tmp0_ = self->priv->_color_depth; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_color_depth (SpiceCtrlController* self, guint32 value) { + guint32 _tmp0_ = 0U; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_color_depth = _tmp0_; + g_object_notify ((GObject *) self, "color-depth"); +} + + +gboolean spice_ctrl_controller_get_enable_usbredir (SpiceCtrlController* self) { + gboolean result; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = self->priv->_enable_usbredir; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_enable_usbredir (SpiceCtrlController* self, gboolean value) { + gboolean _tmp0_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_enable_usbredir = _tmp0_; + g_object_notify ((GObject *) self, "enable-usbredir"); +} + + +gboolean spice_ctrl_controller_get_enable_usb_autoshare (SpiceCtrlController* self) { + gboolean result; + gboolean _tmp0_ = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = self->priv->_enable_usb_autoshare; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_enable_usb_autoshare (SpiceCtrlController* self, gboolean value) { + gboolean _tmp0_ = FALSE; + g_return_if_fail (self != NULL); + _tmp0_ = value; + self->priv->_enable_usb_autoshare = _tmp0_; + g_object_notify ((GObject *) self, "enable-usb-autoshare"); +} + + +const gchar* spice_ctrl_controller_get_usb_filter (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_usb_filter; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_usb_filter (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_usb_filter); + self->priv->_usb_filter = _tmp1_; + g_object_notify ((GObject *) self, "usb-filter"); +} + + +const gchar* spice_ctrl_controller_get_proxy (SpiceCtrlController* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_proxy; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_controller_set_proxy (SpiceCtrlController* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_proxy); + self->priv->_proxy = _tmp1_; + g_object_notify ((GObject *) self, "proxy"); +} + + +static void spice_ctrl_controller_class_init (SpiceCtrlControllerClass * klass) { + spice_ctrl_controller_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (SpiceCtrlControllerPrivate)); + G_OBJECT_CLASS (klass)->get_property = _vala_spice_ctrl_controller_get_property; + G_OBJECT_CLASS (klass)->set_property = _vala_spice_ctrl_controller_set_property; + G_OBJECT_CLASS (klass)->finalize = spice_ctrl_controller_finalize; + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_HOST, g_param_spec_string ("host", "host", "host", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_PORT, g_param_spec_uint ("port", "port", "port", 0, G_MAXUINT, 0U, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_SPORT, g_param_spec_uint ("sport", "sport", "sport", 0, G_MAXUINT, 0U, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_PASSWORD, g_param_spec_string ("password", "password", "password", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_DISPLAY_FLAGS, g_param_spec_uint ("display-flags", "display-flags", "display-flags", 0, G_MAXUINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_TLS_CIPHERS, g_param_spec_string ("tls-ciphers", "tls-ciphers", "tls-ciphers", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_HOST_SUBJECT, g_param_spec_string ("host-subject", "host-subject", "host-subject", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_CA_FILE, g_param_spec_string ("ca-file", "ca-file", "ca-file", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_TITLE, g_param_spec_string ("title", "title", "title", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_HOTKEYS, g_param_spec_string ("hotkeys", "hotkeys", "hotkeys", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_SECURE_CHANNELS, g_param_spec_boxed ("secure-channels", "secure-channels", "secure-channels", G_TYPE_STRV, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_DISABLE_CHANNELS, g_param_spec_boxed ("disable-channels", "disable-channels", "disable-channels", G_TYPE_STRV, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_MENU, g_param_spec_object ("menu", "menu", "menu", SPICE_CTRL_TYPE_MENU, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_ENABLE_SMARTCARD, g_param_spec_boolean ("enable-smartcard", "enable-smartcard", "enable-smartcard", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_SEND_CAD, g_param_spec_boolean ("send-cad", "send-cad", "send-cad", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_DISABLE_EFFECTS, g_param_spec_boxed ("disable-effects", "disable-effects", "disable-effects", G_TYPE_STRV, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_COLOR_DEPTH, g_param_spec_uint ("color-depth", "color-depth", "color-depth", 0, G_MAXUINT, 0U, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_ENABLE_USBREDIR, g_param_spec_boolean ("enable-usbredir", "enable-usbredir", "enable-usbredir", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_ENABLE_USB_AUTOSHARE, g_param_spec_boolean ("enable-usb-autoshare", "enable-usb-autoshare", "enable-usb-autoshare", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_USB_FILTER, g_param_spec_string ("usb-filter", "usb-filter", "usb-filter", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_CONTROLLER_PROXY, g_param_spec_string ("proxy", "proxy", "proxy", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_signal_new ("do_connect", SPICE_CTRL_TYPE_CONTROLLER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("show", SPICE_CTRL_TYPE_CONTROLLER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("hide", SPICE_CTRL_TYPE_CONTROLLER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new ("client_connected", SPICE_CTRL_TYPE_CONTROLLER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +} + + +static void spice_ctrl_controller_instance_init (SpiceCtrlController * self) { + self->priv = SPICE_CTRL_CONTROLLER_GET_PRIVATE (self); +} + + +static void spice_ctrl_controller_finalize (GObject* obj) { + SpiceCtrlController * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlController); + _g_free0 (self->priv->_host); + _g_free0 (self->priv->_password); + _g_free0 (self->priv->_tls_ciphers); + _g_free0 (self->priv->_host_subject); + _g_free0 (self->priv->_ca_file); + _g_free0 (self->priv->_title); + _g_free0 (self->priv->_hotkeys); + self->priv->_secure_channels = (_vala_array_free (self->priv->_secure_channels, self->priv->_secure_channels_length1, (GDestroyNotify) g_free), NULL); + self->priv->_disable_channels = (_vala_array_free (self->priv->_disable_channels, self->priv->_disable_channels_length1, (GDestroyNotify) g_free), NULL); + _g_object_unref0 (self->priv->_menu); + self->priv->_disable_effects = (_vala_array_free (self->priv->_disable_effects, self->priv->_disable_effects_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (self->priv->_usb_filter); + _g_free0 (self->priv->_proxy); + _g_object_unref0 (self->priv->excl_connection); + __g_list_free__g_object_unref0_0 (self->priv->clients); + G_OBJECT_CLASS (spice_ctrl_controller_parent_class)->finalize (obj); +} + + +GType spice_ctrl_controller_get_type (void) { + static volatile gsize spice_ctrl_controller_type_id__volatile = 0; + if (g_once_init_enter (&spice_ctrl_controller_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (SpiceCtrlControllerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) spice_ctrl_controller_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SpiceCtrlController), 0, (GInstanceInitFunc) spice_ctrl_controller_instance_init, NULL }; + GType spice_ctrl_controller_type_id; + spice_ctrl_controller_type_id = g_type_register_static (G_TYPE_OBJECT, "SpiceCtrlController", &g_define_type_info, 0); + g_once_init_leave (&spice_ctrl_controller_type_id__volatile, spice_ctrl_controller_type_id); + } + return spice_ctrl_controller_type_id__volatile; +} + + +static void _vala_spice_ctrl_controller_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { + SpiceCtrlController * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlController); + switch (property_id) { + case SPICE_CTRL_CONTROLLER_HOST: + g_value_set_string (value, spice_ctrl_controller_get_host (self)); + break; + case SPICE_CTRL_CONTROLLER_PORT: + g_value_set_uint (value, spice_ctrl_controller_get_port (self)); + break; + case SPICE_CTRL_CONTROLLER_SPORT: + g_value_set_uint (value, spice_ctrl_controller_get_sport (self)); + break; + case SPICE_CTRL_CONTROLLER_PASSWORD: + g_value_set_string (value, spice_ctrl_controller_get_password (self)); + break; + case SPICE_CTRL_CONTROLLER_DISPLAY_FLAGS: + g_value_set_uint (value, spice_ctrl_controller_get_display_flags (self)); + break; + case SPICE_CTRL_CONTROLLER_TLS_CIPHERS: + g_value_set_string (value, spice_ctrl_controller_get_tls_ciphers (self)); + break; + case SPICE_CTRL_CONTROLLER_HOST_SUBJECT: + g_value_set_string (value, spice_ctrl_controller_get_host_subject (self)); + break; + case SPICE_CTRL_CONTROLLER_CA_FILE: + g_value_set_string (value, spice_ctrl_controller_get_ca_file (self)); + break; + case SPICE_CTRL_CONTROLLER_TITLE: + g_value_set_string (value, spice_ctrl_controller_get_title (self)); + break; + case SPICE_CTRL_CONTROLLER_HOTKEYS: + g_value_set_string (value, spice_ctrl_controller_get_hotkeys (self)); + break; + case SPICE_CTRL_CONTROLLER_SECURE_CHANNELS: + { + int length; + g_value_set_boxed (value, spice_ctrl_controller_get_secure_channels (self, &length)); + } + break; + case SPICE_CTRL_CONTROLLER_DISABLE_CHANNELS: + { + int length; + g_value_set_boxed (value, spice_ctrl_controller_get_disable_channels (self, &length)); + } + break; + case SPICE_CTRL_CONTROLLER_MENU: + g_value_set_object (value, spice_ctrl_controller_get_menu (self)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_SMARTCARD: + g_value_set_boolean (value, spice_ctrl_controller_get_enable_smartcard (self)); + break; + case SPICE_CTRL_CONTROLLER_SEND_CAD: + g_value_set_boolean (value, spice_ctrl_controller_get_send_cad (self)); + break; + case SPICE_CTRL_CONTROLLER_DISABLE_EFFECTS: + { + int length; + g_value_set_boxed (value, spice_ctrl_controller_get_disable_effects (self, &length)); + } + break; + case SPICE_CTRL_CONTROLLER_COLOR_DEPTH: + g_value_set_uint (value, spice_ctrl_controller_get_color_depth (self)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_USBREDIR: + g_value_set_boolean (value, spice_ctrl_controller_get_enable_usbredir (self)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_USB_AUTOSHARE: + g_value_set_boolean (value, spice_ctrl_controller_get_enable_usb_autoshare (self)); + break; + case SPICE_CTRL_CONTROLLER_USB_FILTER: + g_value_set_string (value, spice_ctrl_controller_get_usb_filter (self)); + break; + case SPICE_CTRL_CONTROLLER_PROXY: + g_value_set_string (value, spice_ctrl_controller_get_proxy (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void _vala_spice_ctrl_controller_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { + SpiceCtrlController * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlController); + switch (property_id) { + case SPICE_CTRL_CONTROLLER_HOST: + spice_ctrl_controller_set_host (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_PORT: + spice_ctrl_controller_set_port (self, g_value_get_uint (value)); + break; + case SPICE_CTRL_CONTROLLER_SPORT: + spice_ctrl_controller_set_sport (self, g_value_get_uint (value)); + break; + case SPICE_CTRL_CONTROLLER_PASSWORD: + spice_ctrl_controller_set_password (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_DISPLAY_FLAGS: + spice_ctrl_controller_set_display_flags (self, g_value_get_uint (value)); + break; + case SPICE_CTRL_CONTROLLER_TLS_CIPHERS: + spice_ctrl_controller_set_tls_ciphers (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_HOST_SUBJECT: + spice_ctrl_controller_set_host_subject (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_CA_FILE: + spice_ctrl_controller_set_ca_file (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_TITLE: + spice_ctrl_controller_set_title (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_HOTKEYS: + spice_ctrl_controller_set_hotkeys (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_SECURE_CHANNELS: + { + gpointer boxed; + boxed = g_value_get_boxed (value); + spice_ctrl_controller_set_secure_channels (self, boxed, (boxed == NULL) ? 0 : g_strv_length (boxed)); + } + break; + case SPICE_CTRL_CONTROLLER_DISABLE_CHANNELS: + { + gpointer boxed; + boxed = g_value_get_boxed (value); + spice_ctrl_controller_set_disable_channels (self, boxed, (boxed == NULL) ? 0 : g_strv_length (boxed)); + } + break; + case SPICE_CTRL_CONTROLLER_MENU: + spice_ctrl_controller_set_menu (self, g_value_get_object (value)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_SMARTCARD: + spice_ctrl_controller_set_enable_smartcard (self, g_value_get_boolean (value)); + break; + case SPICE_CTRL_CONTROLLER_SEND_CAD: + spice_ctrl_controller_set_send_cad (self, g_value_get_boolean (value)); + break; + case SPICE_CTRL_CONTROLLER_DISABLE_EFFECTS: + { + gpointer boxed; + boxed = g_value_get_boxed (value); + spice_ctrl_controller_set_disable_effects (self, boxed, (boxed == NULL) ? 0 : g_strv_length (boxed)); + } + break; + case SPICE_CTRL_CONTROLLER_COLOR_DEPTH: + spice_ctrl_controller_set_color_depth (self, g_value_get_uint (value)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_USBREDIR: + spice_ctrl_controller_set_enable_usbredir (self, g_value_get_boolean (value)); + break; + case SPICE_CTRL_CONTROLLER_ENABLE_USB_AUTOSHARE: + spice_ctrl_controller_set_enable_usb_autoshare (self, g_value_get_boolean (value)); + break; + case SPICE_CTRL_CONTROLLER_USB_FILTER: + spice_ctrl_controller_set_usb_filter (self, g_value_get_string (value)); + break; + case SPICE_CTRL_CONTROLLER_PROXY: + spice_ctrl_controller_set_proxy (self, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + +static gint _vala_array_length (gpointer array) { + int length; + length = 0; + if (array) { + while (((gpointer*) array)[length]) { + length++; + } + } + return length; +} + + + diff --git a/src/controller/controller.vala b/src/controller/controller.vala new file mode 100644 index 0000000..84b4527 --- /dev/null +++ b/src/controller/controller.vala @@ -0,0 +1,286 @@ +// Copyright (C) 2011 Red Hat, Inc. + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . + +using GLib; +using Custom; +using Win32; +using Spice; +using SpiceProtocol; + +namespace SpiceCtrl { + +public errordomain Error { + VALUE, +} + +public class Controller: Object { + public string host { private set; get; } + public uint32 port { private set; get; } + public uint32 sport { private set; get; } + public string password { private set; get; } + public SpiceProtocol.Controller.Display display_flags { private set; get; } + public string tls_ciphers { private set; get; } + public string host_subject { private set; get; } + public string ca_file { private set; get; } + public string title { private set; get; } + public string hotkeys { private set; get; } + public string[] secure_channels { private set; get; } + public string[] disable_channels { private set; get; } + public SpiceCtrl.Menu? menu { private set; get; } + public bool enable_smartcard { private set; get; } + public bool send_cad { private set; get; } + public string[] disable_effects {private set; get; } + public uint32 color_depth {private set; get; } + public bool enable_usbredir { private set; get; } + public bool enable_usb_autoshare { private set; get; } + public string usb_filter { private set; get; } + public string proxy { private set; get; } + + public signal void do_connect (); + public signal void show (); + public signal void hide (); + + public signal void client_connected (); + + public void menu_item_click_msg (int32 item_id) { + var msg = SpiceProtocol.Controller.MsgValue (); + msg.base.size = (uint32)sizeof (SpiceProtocol.Controller.MsgValue); + msg.base.id = SpiceProtocol.Controller.MsgId.MENU_ITEM_CLICK; + msg.value = item_id; + unowned uint8[] p = ((uint8[])(&msg))[0:msg.base.size]; + send_msg.begin (p); + } + + public async bool send_msg (uint8[] p) throws GLib.Error { + // vala FIXME: pass Controller.Msg instead + // vala doesn't keep reference on the struct in async methods + // it copies only base, which is not enough to transmit the whole + // message. + try { + if (excl_connection != null) { + yield output_stream_write (excl_connection.output_stream, p); + } else { + foreach (var c in clients) + yield output_stream_write (c.output_stream, p); + } + } catch (GLib.Error e) { + warning (e.message); + } + + return true; + } + + private GLib.IOStream? excl_connection; + private int nclients; + List clients; + + private bool handle_message (SpiceProtocol.Controller.Msg* msg) { + var v = (SpiceProtocol.Controller.MsgValue*)(msg); + var d = (SpiceProtocol.Controller.MsgData*)(msg); + unowned string str = (string)(&d.data); + + switch (msg.id) { + case SpiceProtocol.Controller.MsgId.HOST: + host = str; + debug ("got HOST: %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.PORT: + port = v.value; + debug ("got PORT: %u".printf (port)); + break; + case SpiceProtocol.Controller.MsgId.SPORT: + sport = v.value; + debug ("got SPORT: %u".printf (sport)); + break; + case SpiceProtocol.Controller.MsgId.PASSWORD: + password = str; + debug ("got PASSWORD"); + break; + + case SpiceProtocol.Controller.MsgId.SECURE_CHANNELS: + secure_channels = str.split(","); + debug ("got SECURE_CHANNELS %s".printf (str)); + break; + + case SpiceProtocol.Controller.MsgId.DISABLE_CHANNELS: + disable_channels = str.split(","); + debug ("got DISABLE_CHANNELS %s".printf (str)); + break; + + case SpiceProtocol.Controller.MsgId.TLS_CIPHERS: + tls_ciphers = str; + debug ("got TLS_CIPHERS %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.CA_FILE: + ca_file = str; + debug ("got CA_FILE %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.HOST_SUBJECT: + host_subject = str; + debug ("got HOST_SUBJECT %s".printf (str)); + break; + + case SpiceProtocol.Controller.MsgId.FULL_SCREEN: + display_flags = (SpiceProtocol.Controller.Display)v.value; + debug ("got FULL_SCREEN 0x%x".printf (v.value)); + break; + case SpiceProtocol.Controller.MsgId.SET_TITLE: + title = str; + debug ("got TITLE %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.ENABLE_SMARTCARD: + enable_smartcard = (bool)v.value; + debug ("got ENABLE_SMARTCARD 0x%x".printf (v.value)); + break; + + case SpiceProtocol.Controller.MsgId.CREATE_MENU: + menu = new SpiceCtrl.Menu.from_string (str); + debug ("got CREATE_MENU %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.DELETE_MENU: + menu = null; + debug ("got DELETE_MENU request"); + break; + + case SpiceProtocol.Controller.MsgId.SEND_CAD: + send_cad = (bool)v.value; + debug ("got SEND_CAD %u".printf (v.value)); + break; + + case SpiceProtocol.Controller.MsgId.HOTKEYS: + hotkeys = str; + debug ("got HOTKEYS %s".printf (str)); + break; + + case SpiceProtocol.Controller.MsgId.COLOR_DEPTH: + color_depth = v.value; + debug ("got COLOR_DEPTH %u".printf (v.value)); + break; + case SpiceProtocol.Controller.MsgId.DISABLE_EFFECTS: + disable_effects = str.split(","); + debug ("got DISABLE_EFFECTS %s".printf (str)); + break; + + case SpiceProtocol.Controller.MsgId.CONNECT: + do_connect (); + debug ("got CONNECT request"); + break; + case SpiceProtocol.Controller.MsgId.SHOW: + show (); + debug ("got SHOW request"); + break; + case SpiceProtocol.Controller.MsgId.HIDE: + hide (); + debug ("got HIDE request"); + break; + case SpiceProtocol.Controller.MsgId.ENABLE_USB: + enable_usbredir = (bool)v.value; + debug ("got ENABLE_USB %u".printf (v.value)); + break; + case SpiceProtocol.Controller.MsgId.ENABLE_USB_AUTOSHARE: + enable_usb_autoshare = (bool)v.value; + debug ("got ENABLE_USB_AUTOSHARE %u".printf (v.value)); + break; + case SpiceProtocol.Controller.MsgId.USB_FILTER: + usb_filter = str; + debug ("got USB_FILTER %s".printf (str)); + break; + case SpiceProtocol.Controller.MsgId.PROXY: + proxy = str; + debug ("got PROXY %s".printf (str)); + break; + default: + debug ("got unknown msg.id %u".printf (msg.id)); + warn_if_reached (); + return false; + } + return true; + } + + private async void handle_client (IOStream c) throws GLib.Error { + var excl = false; + + debug ("new socket client, reading init header"); + + var p = new uint8[sizeof(SpiceProtocol.Controller.Init)]; + var init = (SpiceProtocol.Controller.Init*)p; + yield input_stream_read (c.input_stream, p); + if (warn_if (init.base.magic != SpiceProtocol.Controller.MAGIC)) + return; + if (warn_if (init.base.version != SpiceProtocol.Controller.VERSION)) + return; + if (warn_if (init.base.size < sizeof (SpiceProtocol.Controller.Init))) + return; + if (warn_if (init.credentials != 0)) + return; + if (warn_if (excl_connection != null)) + return; + + excl = (bool)(init.flags & SpiceProtocol.Controller.Flag.EXCLUSIVE); + if (excl) { + if (nclients > 1) { + warning (@"Can't make the client exclusive, there is already $nclients connected clients"); + return; + } + excl_connection = c; + } + + client_connected (); + + for (;;) { + var t = new uint8[sizeof(SpiceProtocol.Controller.Msg)]; + yield input_stream_read (c.input_stream, t); + var msg = (SpiceProtocol.Controller.Msg*)t; + debug ("new message " + msg.id.to_string () + "size " + msg.size.to_string ()); + if (warn_if (msg.size < sizeof (SpiceProtocol.Controller.Msg))) + break; + + if (msg.size > sizeof (SpiceProtocol.Controller.Msg)) { + t.resize ((int)msg.size); + msg = (SpiceProtocol.Controller.Msg*)t; + yield input_stream_read (c.input_stream, t[sizeof(SpiceProtocol.Controller.Msg):msg.size]); + } + + handle_message (msg); + } + + if (excl) + excl_connection = null; + } + + public Controller() { + } + + public async void listen (string? addr = null) throws GLib.Error, SpiceCtrl.Error + { + var listener = ControllerListener.new_listener (addr); + + for (;;) { + var c = yield listener.accept_async (); + nclients += 1; + clients.append (c); + try { + yield handle_client (c); + } catch (GLib.Error e) { + warning (e.message); + } + c.close (); + clients.remove (c); + nclients -= 1; + } + } +} + +} // SpiceCtrl diff --git a/src/controller/controller.vala.stamp b/src/controller/controller.vala.stamp new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/custom.h b/src/controller/custom.h new file mode 100644 index 0000000..7f849fc --- /dev/null +++ b/src/controller/custom.h @@ -0,0 +1,22 @@ +#ifndef CUSTOM_H_ +#define CUSTOM_H_ + +#include + +static inline gboolean g_warn_if_expr (gboolean condition, + const char *pretty_func, + const char *expression) { + if G_UNLIKELY(condition) { + g_log (G_LOG_DOMAIN, + G_LOG_LEVEL_CRITICAL, + "%s: `%s' condition reached", + pretty_func, + expression); + } + + return condition; +} + +#define g_warn_if(expr) g_warn_if_expr((expr), __PRETTY_FUNCTION__, #expr) + +#endif diff --git a/src/controller/custom.vapi b/src/controller/custom.vapi new file mode 100644 index 0000000..a12fdec --- /dev/null +++ b/src/controller/custom.vapi @@ -0,0 +1,28 @@ +using GLib; + +namespace Custom { + + [CCode (cname = "g_warn_if", cheader_filename = "custom.h")] + public bool warn_if(bool condition); +} + +namespace Spice { + + [CCode (cname = "GObject", ref_function = "g_object_ref", unref_function = "g_object_unref", free_function = "")] + class ControllerListener { + [CCode (cname = "spice_controller_listener_new", cheader_filename = "spice-controller-listener.h")] + public static ControllerListener new_listener (string addr) throws GLib.Error; + + [CCode (cname = "spice_controller_listener_accept_async", cheader_filename = "spice-controller-listener.h")] + public async unowned GLib.IOStream accept_async (GLib.Cancellable? cancellable = null, out GLib.Object? source_object = null) throws GLib.Error; + } + + [CCode (cname = "GObject", ref_function = "g_object_ref", unref_function = "g_object_unref", free_function = "")] + class ForeignMenuListener { + [CCode (cname = "spice_foreign_menu_listener_new", cheader_filename = "spice-foreign-menu-listener.h")] + public static ForeignMenuListener new_listener (string addr) throws GLib.Error; + + [CCode (cname = "spice_foreign_menu_listener_accept_async", cheader_filename = "spice-foreign-menu-listener.h")] + public async unowned GLib.IOStream accept_async (GLib.Cancellable? cancellable = null, out GLib.Object? source_object = null) throws GLib.Error; + } +} diff --git a/src/controller/dump.c b/src/controller/dump.c new file mode 100644 index 0000000..b260264 --- /dev/null +++ b/src/controller/dump.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2011 Red Hat, Inc. */ + +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2.1 of the License, or (at your option) any later version. */ + +/* This library is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* Lesser General Public License for more details. */ + +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; if not, see . */ + +#include "config.h" + +#include +#include + +#ifdef WIN32 +#include +#else +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include +#endif + +#include "spice-controller.h" + +SpiceCtrlController *ctrl = NULL; +SpiceCtrlForeignMenu *menu = NULL; +GMainLoop *loop = NULL; + +void signaled (GObject *gobject, const gchar *signal_name) +{ + g_message ("signaled: %s", signal_name); +} + +void notified (GObject *gobject, GParamSpec *pspec, + gpointer user_data) +{ + GValue value = { 0, }; + GValue strvalue = { 0, }; + + g_return_if_fail (gobject != NULL); + g_return_if_fail (pspec != NULL); + + g_value_init (&value, pspec->value_type); + g_value_init (&strvalue, G_TYPE_STRING); + g_object_get_property (gobject, pspec->name, &value); + + if (pspec->value_type == G_TYPE_STRV) { + gchar** p = (gchar **)g_value_get_boxed (&value); + g_message ("notify::%s == ", pspec->name); + while (*p) + g_message ("%s", *p++); + } else if (G_TYPE_IS_OBJECT(pspec->value_type)) { + GObject *o = g_value_get_object (&value); + g_message ("notify::%s == %s", pspec->name, o ? G_OBJECT_TYPE_NAME (o) : "null"); + } else { + g_value_transform (&value, &strvalue); + g_message ("notify::%s = %s", pspec->name, g_value_get_string (&strvalue)); + } + + g_value_unset (&value); + g_value_unset (&strvalue); +} + +void connect_signals (gpointer obj) +{ + guint i, n_ids = 0; + guint *ids = NULL; + GType type = G_OBJECT_TYPE (obj); + + ids = g_signal_list_ids (type, &n_ids); + for (i = 0; i < n_ids; i++) { + const gchar *name = g_signal_name (ids[i]); + g_signal_connect (obj, name, G_CALLBACK (signaled), (gpointer)name); + } +} + +int main (int argc, char *argv[]) +{ + loop = g_main_loop_new (NULL, FALSE); + + if (argc > 1 && g_str_equal(argv[1], "--menu")) { + menu = spice_ctrl_foreign_menu_new (); + g_signal_connect (menu, "notify", G_CALLBACK (notified), NULL); + connect_signals (menu); + + spice_ctrl_foreign_menu_listen (menu, NULL, NULL, NULL); + } else { + ctrl = spice_ctrl_controller_new (); + g_signal_connect (ctrl, "notify", G_CALLBACK (notified), NULL); + connect_signals (ctrl); + + spice_ctrl_controller_listen (ctrl, NULL, NULL, NULL); + } + + g_main_loop_run (loop); + + if (ctrl != NULL) + g_object_unref (ctrl); + if (menu != NULL) + g_object_unref (menu); + + return 0; +} diff --git a/src/controller/foreign-menu.c b/src/controller/foreign-menu.c new file mode 100644 index 0000000..d1d6548 --- /dev/null +++ b/src/controller/foreign-menu.c @@ -0,0 +1,1490 @@ +/* foreign-menu.c generated by valac 0.32.0, the Vala compiler + * generated from foreign-menu.vala, do not modify */ + +/* Copyright (C) 2012 Red Hat, Inc.*/ +/* This library is free software; you can redistribute it and/or*/ +/* modify it under the terms of the GNU Lesser General Public*/ +/* License as published by the Free Software Foundation; either*/ +/* version 2.1 of the License, or (at your option) any later version.*/ +/* This library is distributed in the hope that it will be useful,*/ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of*/ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU*/ +/* Lesser General Public License for more details.*/ +/* You should have received a copy of the GNU Lesser General Public*/ +/* License along with this library; if not, see .*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SPICE_CTRL_TYPE_FOREIGN_MENU (spice_ctrl_foreign_menu_get_type ()) +#define SPICE_CTRL_FOREIGN_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenu)) +#define SPICE_CTRL_FOREIGN_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenuClass)) +#define SPICE_CTRL_IS_FOREIGN_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU)) +#define SPICE_CTRL_IS_FOREIGN_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_FOREIGN_MENU)) +#define SPICE_CTRL_FOREIGN_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenuClass)) + +typedef struct _SpiceCtrlForeignMenu SpiceCtrlForeignMenu; +typedef struct _SpiceCtrlForeignMenuClass SpiceCtrlForeignMenuClass; +typedef struct _SpiceCtrlForeignMenuPrivate SpiceCtrlForeignMenuPrivate; + +#define SPICE_CTRL_TYPE_MENU (spice_ctrl_menu_get_type ()) +#define SPICE_CTRL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenu)) +#define SPICE_CTRL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) +#define SPICE_CTRL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) + +typedef struct _SpiceCtrlMenu SpiceCtrlMenu; +typedef struct _SpiceCtrlMenuClass SpiceCtrlMenuClass; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +#define __g_list_free__g_object_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__g_object_unref0_ (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +typedef struct _SpiceCtrlForeignMenuSendMsgData SpiceCtrlForeignMenuSendMsgData; +typedef struct _SpiceCtrlMenuPrivate SpiceCtrlMenuPrivate; + +#define SPICE_CTRL_TYPE_MENU_ITEM (spice_ctrl_menu_item_get_type ()) +#define SPICE_CTRL_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItem)) +#define SPICE_CTRL_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) +#define SPICE_CTRL_IS_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) + +typedef struct _SpiceCtrlMenuItem SpiceCtrlMenuItem; +typedef struct _SpiceCtrlMenuItemClass SpiceCtrlMenuItemClass; +typedef struct _SpiceCtrlForeignMenuHandleClientData SpiceCtrlForeignMenuHandleClientData; +typedef struct _SpiceCtrlForeignMenuListenData SpiceCtrlForeignMenuListenData; + +struct _SpiceCtrlForeignMenu { + GObject parent_instance; + SpiceCtrlForeignMenuPrivate * priv; +}; + +struct _SpiceCtrlForeignMenuClass { + GObjectClass parent_class; +}; + +struct _SpiceCtrlForeignMenuPrivate { + SpiceCtrlMenu* _menu; + gchar* _title; + gint nclients; + GList* clients; +}; + +struct _SpiceCtrlForeignMenuSendMsgData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlForeignMenu* self; + guint8* p; + gint p_length1; + gboolean result; + GList* _tmp0_; + GList* c_collection; + GList* c_it; + GIOStream* _tmp1_; + GIOStream* c; + GIOStream* _tmp2_; + GOutputStream* _tmp3_; + GOutputStream* _tmp4_; + guint8* _tmp5_; + gint _tmp5__length1; + guint8* _tmp6_; + gint _tmp6__length1; + GError* e; + GError* _tmp7_; + const gchar* _tmp8_; + GError * _inner_error_; +}; + +struct _SpiceCtrlMenu { + GObject parent_instance; + SpiceCtrlMenuPrivate * priv; + GList* items; +}; + +struct _SpiceCtrlMenuClass { + GObjectClass parent_class; +}; + +struct _SpiceCtrlForeignMenuHandleClientData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlForeignMenu* self; + GIOStream* c; + guint8* p; + guint8* _tmp0_; + gint p_length1; + gint _p_size_; + FrgMenuInitHeader* header; + guint8* _tmp1_; + gint _tmp1__length1; + GIOStream* _tmp2_; + GInputStream* _tmp3_; + GInputStream* _tmp4_; + guint8* _tmp5_; + gint _tmp5__length1; + FrgMenuInitHeader* _tmp6_; + guint32 _tmp7_; + gboolean _tmp8_; + FrgMenuInitHeader* _tmp9_; + guint32 _tmp10_; + gboolean _tmp11_; + FrgMenuInitHeader* _tmp12_; + guint32 _tmp13_; + gboolean _tmp14_; + guint8* cp; + guint8* _tmp15_; + gint cp_length1; + gint _cp_size_; + GIOStream* _tmp16_; + GInputStream* _tmp17_; + GInputStream* _tmp18_; + guint8* _tmp19_; + gint _tmp19__length1; + guint64 credentials; + guint8* _tmp20_; + gint _tmp20__length1; + guint64 _tmp21_; + gboolean _tmp22_; + gulong title_size; + FrgMenuInitHeader* _tmp23_; + guint32 _tmp24_; + guint8* title; + gulong _tmp25_; + guint8* _tmp26_; + gint title_length1; + gint _title_size_; + GIOStream* _tmp27_; + GInputStream* _tmp28_; + GInputStream* _tmp29_; + guint8* _tmp30_; + gint _tmp30__length1; + gulong _tmp31_; + guint8* _tmp32_; + gint _tmp32__length1; + gboolean _tmp33_; + guint8* t; + guint8* _tmp34_; + gint t_length1; + gint _t_size_; + GIOStream* _tmp35_; + GInputStream* _tmp36_; + GInputStream* _tmp37_; + guint8* _tmp38_; + gint _tmp38__length1; + FrgMenuMsg* msg; + guint8* _tmp39_; + gint _tmp39__length1; + FrgMenuMsg* _tmp40_; + guint32 _tmp41_; + gchar* _tmp42_; + gchar* _tmp43_; + gchar* _tmp44_; + gchar* _tmp45_; + gchar* _tmp46_; + gchar* _tmp47_; + FrgMenuMsg* _tmp48_; + guint32 _tmp49_; + gchar* _tmp50_; + gchar* _tmp51_; + gchar* _tmp52_; + gchar* _tmp53_; + FrgMenuMsg* _tmp54_; + guint32 _tmp55_; + gboolean _tmp56_; + FrgMenuMsg* _tmp57_; + guint32 _tmp58_; + FrgMenuMsg* _tmp59_; + guint32 _tmp60_; + gint _tmp61_; + guint8* _tmp62_; + gint _tmp62__length1; + GIOStream* _tmp63_; + GInputStream* _tmp64_; + GInputStream* _tmp65_; + guint8* _tmp66_; + gint _tmp66__length1; + FrgMenuMsg* _tmp67_; + guint32 _tmp68_; + FrgMenuMsg* _tmp69_; + GError * _inner_error_; +}; + +typedef enum { + SPICE_CTRL_ERROR_VALUE +} SpiceCtrlError; +#define SPICE_CTRL_ERROR spice_ctrl_error_quark () +struct _SpiceCtrlForeignMenuListenData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + SpiceCtrlForeignMenu* self; + gchar* addr; + GObject* listener; + const gchar* _tmp0_; + GObject* _tmp1_; + gboolean _tmp2_; + GIOStream* c; + GObject* _tmp3_; + GIOStream* _tmp4_; + GIOStream* _tmp5_; + gint _tmp6_; + GIOStream* _tmp7_; + GIOStream* _tmp8_; + GIOStream* _tmp9_; + GError* e; + GError* _tmp10_; + const gchar* _tmp11_; + GIOStream* _tmp12_; + GIOStream* _tmp13_; + gint _tmp14_; + GError * _inner_error_; +}; + + +static gpointer spice_ctrl_foreign_menu_parent_class = NULL; + +GType spice_ctrl_foreign_menu_get_type (void) G_GNUC_CONST; +GType spice_ctrl_menu_get_type (void) G_GNUC_CONST; +#define SPICE_CTRL_FOREIGN_MENU_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenuPrivate)) +enum { + SPICE_CTRL_FOREIGN_MENU_DUMMY_PROPERTY, + SPICE_CTRL_FOREIGN_MENU_MENU, + SPICE_CTRL_FOREIGN_MENU_TITLE +}; +static void _g_object_unref0_ (gpointer var); +static void _g_list_free__g_object_unref0_ (GList* self); +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_new (void); +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_construct (GType object_type); +SpiceCtrlMenu* spice_ctrl_menu_new (void); +SpiceCtrlMenu* spice_ctrl_menu_construct (GType object_type); +static void spice_ctrl_foreign_menu_set_menu (SpiceCtrlForeignMenu* self, SpiceCtrlMenu* value); +void spice_ctrl_foreign_menu_menu_item_click_msg (SpiceCtrlForeignMenu* self, gint32 item_id); +void spice_ctrl_foreign_menu_send_msg (SpiceCtrlForeignMenu* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +gboolean spice_ctrl_foreign_menu_send_msg_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error); +static guint8* _vala_array_dup6 (guint8* self, int length); +void spice_ctrl_foreign_menu_menu_item_checked_msg (SpiceCtrlForeignMenu* self, gint32 item_id, gboolean checked); +static guint8* _vala_array_dup7 (guint8* self, int length); +void spice_ctrl_foreign_menu_app_activated_msg (SpiceCtrlForeignMenu* self, gboolean activated); +static guint8* _vala_array_dup8 (guint8* self, int length); +static void spice_ctrl_foreign_menu_send_msg_data_free (gpointer _data); +static gboolean spice_ctrl_foreign_menu_send_msg_co (SpiceCtrlForeignMenuSendMsgData* _data_); +void spice_ctrl_output_stream_write (GOutputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_output_stream_write_finish (GAsyncResult* _res_, GError** error); +static guint8* _vala_array_dup9 (guint8* self, int length); +static void spice_ctrl_foreign_menu_send_msg_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +static unsigned int spice_ctrl_foreign_menu_get_menu_flags (SpiceCtrlForeignMenu* self, guint32 type); +static gboolean spice_ctrl_foreign_menu_handle_message (SpiceCtrlForeignMenu* self, FrgMenuMsg* msg); +static void spice_ctrl_foreign_menu_set_title (SpiceCtrlForeignMenu* self, const gchar* value); +SpiceCtrlMenu* spice_ctrl_foreign_menu_get_menu (SpiceCtrlForeignMenu* self); +GType spice_ctrl_menu_item_get_type (void) G_GNUC_CONST; +SpiceCtrlMenuItem* spice_ctrl_menu_item_new (gint id, const gchar* text, unsigned int flags); +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct (GType object_type, gint id, const gchar* text, unsigned int flags); +static void spice_ctrl_foreign_menu_handle_client_data_free (gpointer _data); +static void spice_ctrl_foreign_menu_handle_client (SpiceCtrlForeignMenu* self, GIOStream* c, GAsyncReadyCallback _callback_, gpointer _user_data_); +static void spice_ctrl_foreign_menu_handle_client_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_foreign_menu_handle_client_co (SpiceCtrlForeignMenuHandleClientData* _data_); +void spice_ctrl_input_stream_read (GInputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_input_stream_read_finish (GAsyncResult* _res_, GError** error); +static void spice_ctrl_foreign_menu_handle_client_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +static void spice_ctrl_foreign_menu_listen_data_free (gpointer _data); +GQuark spice_ctrl_error_quark (void); +void spice_ctrl_foreign_menu_listen (SpiceCtrlForeignMenu* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_foreign_menu_listen_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_foreign_menu_listen_co (SpiceCtrlForeignMenuListenData* _data_); +static void spice_ctrl_foreign_menu_listen_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +const gchar* spice_ctrl_foreign_menu_get_title (SpiceCtrlForeignMenu* self); +static void spice_ctrl_foreign_menu_finalize (GObject* obj); +static void _vala_spice_ctrl_foreign_menu_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); +static void _vala_spice_ctrl_foreign_menu_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); + + +static void _g_object_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (g_object_unref (var), NULL)); +} + + +static void _g_list_free__g_object_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _g_object_unref0_, NULL); + g_list_free (self); +} + + +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_construct (GType object_type) { + SpiceCtrlForeignMenu * self = NULL; + SpiceCtrlMenu* _tmp0_ = NULL; + SpiceCtrlMenu* _tmp1_ = NULL; + self = (SpiceCtrlForeignMenu*) g_object_new (object_type, NULL); + _tmp0_ = spice_ctrl_menu_new (); + _tmp1_ = _tmp0_; + spice_ctrl_foreign_menu_set_menu (self, _tmp1_); + _g_object_unref0 (_tmp1_); + return self; +} + + +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_new (void) { + return spice_ctrl_foreign_menu_construct (SPICE_CTRL_TYPE_FOREIGN_MENU); +} + + +static guint8* _vala_array_dup6 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +void spice_ctrl_foreign_menu_menu_item_click_msg (SpiceCtrlForeignMenu* self, gint32 item_id) { + gint32 _tmp0_ = 0; + gchar* _tmp1_ = NULL; + gchar* _tmp2_ = NULL; + FrgMenuEvent msg = {0}; + gint32 _tmp3_ = 0; + guint8* p = NULL; + FrgMenuEvent _tmp4_ = {0}; + FrgMenuMsg _tmp5_ = {0}; + guint32 _tmp6_ = 0U; + gint p_length1 = 0; + gint _p_size_ = 0; + guint8* _tmp7_ = NULL; + gint _tmp7__length1 = 0; + g_return_if_fail (self != NULL); + _tmp0_ = item_id; + _tmp1_ = g_strdup_printf ("clicked id: %d", (gint) _tmp0_); + _tmp2_ = _tmp1_; + g_debug ("foreign-menu.vala:35: %s", _tmp2_); + _g_free0 (_tmp2_); + memset (&msg, 0, sizeof (FrgMenuEvent)); + msg.base.size = (guint32) sizeof (FrgMenuEvent); + msg.base.id = (guint32) FOREIGN_MENU_ITEM_EVENT; + _tmp3_ = item_id; + msg.id = (guint32) _tmp3_; + msg.action = (guint32) FOREIGN_MENU_EVENT_CLICK; + _tmp4_ = msg; + _tmp5_ = _tmp4_.base; + _tmp6_ = _tmp5_.size; + p = ((guint8*) (&msg)) + 0; + p_length1 = ((gint) _tmp6_) - 0; + _p_size_ = p_length1; + _tmp7_ = (p != NULL) ? _vala_array_dup6 (p, p_length1) : ((gpointer) p); + _tmp7__length1 = p_length1; + spice_ctrl_foreign_menu_send_msg (self, _tmp7_, _tmp7__length1, NULL, NULL); +} + + +static guint8* _vala_array_dup7 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +void spice_ctrl_foreign_menu_menu_item_checked_msg (SpiceCtrlForeignMenu* self, gint32 item_id, gboolean checked) { + const gchar* _tmp0_ = NULL; + gboolean _tmp1_ = FALSE; + gint32 _tmp2_ = 0; + gchar* _tmp3_ = NULL; + gchar* _tmp4_ = NULL; + FrgMenuEvent msg = {0}; + gint32 _tmp5_ = 0; + int _tmp6_ = 0; + gboolean _tmp7_ = FALSE; + guint8* p = NULL; + FrgMenuEvent _tmp8_ = {0}; + FrgMenuMsg _tmp9_ = {0}; + guint32 _tmp10_ = 0U; + gint p_length1 = 0; + gint _p_size_ = 0; + guint8* _tmp11_ = NULL; + gint _tmp11__length1 = 0; + g_return_if_fail (self != NULL); + _tmp1_ = checked; + if (_tmp1_) { + _tmp0_ = ""; + } else { + _tmp0_ = "un"; + } + _tmp2_ = item_id; + _tmp3_ = g_strdup_printf ("%schecked id: %d", _tmp0_, (gint) _tmp2_); + _tmp4_ = _tmp3_; + g_debug ("foreign-menu.vala:48: %s", _tmp4_); + _g_free0 (_tmp4_); + memset (&msg, 0, sizeof (FrgMenuEvent)); + msg.base.size = (guint32) sizeof (FrgMenuEvent); + msg.base.id = (guint32) FOREIGN_MENU_ITEM_EVENT; + _tmp5_ = item_id; + msg.id = (guint32) _tmp5_; + _tmp7_ = checked; + if (_tmp7_) { + _tmp6_ = FOREIGN_MENU_EVENT_CHECKED; + } else { + _tmp6_ = FOREIGN_MENU_EVENT_UNCHECKED; + } + msg.action = (guint32) _tmp6_; + _tmp8_ = msg; + _tmp9_ = _tmp8_.base; + _tmp10_ = _tmp9_.size; + p = ((guint8*) (&msg)) + 0; + p_length1 = ((gint) _tmp10_) - 0; + _p_size_ = p_length1; + _tmp11_ = (p != NULL) ? _vala_array_dup7 (p, p_length1) : ((gpointer) p); + _tmp11__length1 = p_length1; + spice_ctrl_foreign_menu_send_msg (self, _tmp11_, _tmp11__length1, NULL, NULL); +} + + +static guint8* _vala_array_dup8 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +void spice_ctrl_foreign_menu_app_activated_msg (SpiceCtrlForeignMenu* self, gboolean activated) { + FrgMenuMsg msg = {0}; + int _tmp0_ = 0; + gboolean _tmp1_ = FALSE; + guint8* p = NULL; + FrgMenuMsg _tmp2_ = {0}; + guint32 _tmp3_ = 0U; + gint p_length1 = 0; + gint _p_size_ = 0; + guint8* _tmp4_ = NULL; + gint _tmp4__length1 = 0; + g_return_if_fail (self != NULL); + memset (&msg, 0, sizeof (FrgMenuMsg)); + msg.size = (guint32) sizeof (FrgMenuEvent); + _tmp1_ = activated; + if (_tmp1_) { + _tmp0_ = FOREIGN_MENU_APP_ACTIVATED; + } else { + _tmp0_ = FOREIGN_MENU_APP_DEACTIVATED; + } + msg.id = (guint32) _tmp0_; + _tmp2_ = msg; + _tmp3_ = _tmp2_.size; + p = ((guint8*) (&msg)) + 0; + p_length1 = ((gint) _tmp3_) - 0; + _p_size_ = p_length1; + _tmp4_ = (p != NULL) ? _vala_array_dup8 (p, p_length1) : ((gpointer) p); + _tmp4__length1 = p_length1; + spice_ctrl_foreign_menu_send_msg (self, _tmp4_, _tmp4__length1, NULL, NULL); +} + + +static void spice_ctrl_foreign_menu_send_msg_data_free (gpointer _data) { + SpiceCtrlForeignMenuSendMsgData* _data_; + _data_ = _data; + _data_->p = (g_free (_data_->p), NULL); + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlForeignMenuSendMsgData, _data_); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +void spice_ctrl_foreign_menu_send_msg (SpiceCtrlForeignMenu* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlForeignMenuSendMsgData* _data_; + SpiceCtrlForeignMenu* _tmp0_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlForeignMenuSendMsgData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_foreign_menu_send_msg); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_foreign_menu_send_msg_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _data_->p = (g_free (_data_->p), NULL); + _data_->p = p; + _data_->p_length1 = p_length1; + spice_ctrl_foreign_menu_send_msg_co (_data_); +} + + +gboolean spice_ctrl_foreign_menu_send_msg_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error) { + gboolean result; + SpiceCtrlForeignMenuSendMsgData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return FALSE; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); + result = _data_->result; + return result; +} + + +static guint8* _vala_array_dup9 (guint8* self, int length) { + return g_memdup (self, length * sizeof (guint8)); +} + + +static void spice_ctrl_foreign_menu_send_msg_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlForeignMenuSendMsgData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_foreign_menu_send_msg_co (_data_); +} + + +static gboolean spice_ctrl_foreign_menu_send_msg_co (SpiceCtrlForeignMenuSendMsgData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + default: + g_assert_not_reached (); + } + _state_0: + { + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = _data_->self->priv->clients; + { + _data_->c_collection = _data_->_tmp0_; + for (_data_->c_it = _data_->c_collection; _data_->c_it != NULL; _data_->c_it = _data_->c_it->next) { + _data_->_tmp1_ = NULL; + _data_->_tmp1_ = _g_object_ref0 ((GIOStream*) _data_->c_it->data); + _data_->c = _data_->_tmp1_; + { + _data_->_tmp2_ = NULL; + _data_->_tmp2_ = _data_->c; + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = g_io_stream_get_output_stream (_data_->_tmp2_); + _data_->_tmp4_ = NULL; + _data_->_tmp4_ = _data_->_tmp3_; + _data_->_tmp5_ = NULL; + _data_->_tmp5__length1 = 0; + _data_->_tmp5_ = _data_->p; + _data_->_tmp5__length1 = _data_->p_length1; + _data_->_tmp6_ = NULL; + _data_->_tmp6__length1 = 0; + _data_->_tmp6_ = (_data_->_tmp5_ != NULL) ? _vala_array_dup9 (_data_->_tmp5_, _data_->_tmp5__length1) : ((gpointer) _data_->_tmp5_); + _data_->_tmp6__length1 = _data_->_tmp5__length1; + _data_->_state_ = 1; + spice_ctrl_output_stream_write (_data_->_tmp4_, _data_->_tmp6_, _data_->_tmp6__length1, spice_ctrl_foreign_menu_send_msg_ready, _data_); + return FALSE; + _state_1: + spice_ctrl_output_stream_write_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + _g_object_unref0 (_data_->c); + goto __catch3_g_error; + } + _g_object_unref0 (_data_->c); + } + } + } + } + goto __finally3; + __catch3_g_error: + { + _data_->e = _data_->_inner_error_; + _data_->_inner_error_ = NULL; + _data_->_tmp7_ = NULL; + _data_->_tmp7_ = _data_->e; + _data_->_tmp8_ = NULL; + _data_->_tmp8_ = _data_->_tmp7_->message; + g_warning ("foreign-menu.vala:83: %s", _data_->_tmp8_); + _g_error_free0 (_data_->e); + } + __finally3: + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->result = TRUE; + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +static unsigned int spice_ctrl_foreign_menu_get_menu_flags (SpiceCtrlForeignMenu* self, guint32 type) { + unsigned int result = 0; + unsigned int flags = 0; + guint32 _tmp0_ = 0U; + guint32 _tmp2_ = 0U; + g_return_val_if_fail (self != NULL, 0); + flags = 0; + _tmp0_ = type; + if ((FOREIGN_MENU_ITEM_TYPE_CHECKED & _tmp0_) != 0) { + unsigned int _tmp1_ = 0; + _tmp1_ = flags; + flags = _tmp1_ | CONTROLLER_MENU_FLAGS_CHECKED; + } + _tmp2_ = type; + if ((FOREIGN_MENU_ITEM_TYPE_DIM & _tmp2_) != 0) { + unsigned int _tmp3_ = 0; + _tmp3_ = flags; + flags = _tmp3_ | CONTROLLER_MENU_FLAGS_GRAYED; + } + result = flags; + return result; +} + + +static gboolean spice_ctrl_foreign_menu_handle_message (SpiceCtrlForeignMenu* self, FrgMenuMsg* msg) { + gboolean result = FALSE; + FrgMenuMsg* _tmp0_ = NULL; + guint32 _tmp1_ = 0U; + g_return_val_if_fail (self != NULL, FALSE); + _tmp0_ = msg; + _tmp1_ = (*_tmp0_).id; + switch (_tmp1_) { + case FOREIGN_MENU_SET_TITLE: + { + FrgMenuSetTitle* t = NULL; + FrgMenuMsg* _tmp2_ = NULL; + FrgMenuSetTitle* _tmp3_ = NULL; + const gchar* _tmp4_ = NULL; + _tmp2_ = msg; + t = (FrgMenuSetTitle*) _tmp2_; + _tmp3_ = t; + _tmp4_ = (*_tmp3_).string; + spice_ctrl_foreign_menu_set_title (self, _tmp4_); + break; + } + case FOREIGN_MENU_ADD_ITEM: + { + FrgMenuAddItem* i = NULL; + FrgMenuMsg* _tmp5_ = NULL; + FrgMenuAddItem* _tmp6_ = NULL; + guint32 _tmp7_ = 0U; + FrgMenuAddItem* _tmp8_ = NULL; + guint32 _tmp9_ = 0U; + FrgMenuAddItem* _tmp10_ = NULL; + guint32 _tmp11_ = 0U; + FrgMenuAddItem* _tmp12_ = NULL; + const gchar* _tmp13_ = NULL; + SpiceCtrlMenu* _tmp14_ = NULL; + FrgMenuAddItem* _tmp15_ = NULL; + guint32 _tmp16_ = 0U; + FrgMenuAddItem* _tmp17_ = NULL; + const gchar* _tmp18_ = NULL; + FrgMenuAddItem* _tmp19_ = NULL; + guint32 _tmp20_ = 0U; + unsigned int _tmp21_ = 0; + SpiceCtrlMenuItem* _tmp22_ = NULL; + _tmp5_ = msg; + i = (FrgMenuAddItem*) _tmp5_; + _tmp6_ = i; + _tmp7_ = (*_tmp6_).id; + _tmp8_ = i; + _tmp9_ = (*_tmp8_).type; + _tmp10_ = i; + _tmp11_ = (*_tmp10_).position; + _tmp12_ = i; + _tmp13_ = (*_tmp12_).string; + g_debug ("foreign-menu.vala:108: add id:%u type:%u position:%u title:%s", (guint) _tmp7_, (guint) _tmp9_, (guint) _tmp11_, _tmp13_); + _tmp14_ = self->priv->_menu; + _tmp15_ = i; + _tmp16_ = (*_tmp15_).id; + _tmp17_ = i; + _tmp18_ = (*_tmp17_).string; + _tmp19_ = i; + _tmp20_ = (*_tmp19_).type; + _tmp21_ = spice_ctrl_foreign_menu_get_menu_flags (self, _tmp20_); + _tmp22_ = spice_ctrl_menu_item_new ((gint) _tmp16_, _tmp18_, _tmp21_); + _tmp14_->items = g_list_append (_tmp14_->items, _tmp22_); + g_object_notify ((GObject*) self, "menu"); + break; + } + case FOREIGN_MENU_MODIFY_ITEM: + { + g_debug ("foreign-menu.vala:113: deprecated: modify item"); + break; + } + case FOREIGN_MENU_REMOVE_ITEM: + { + FrgMenuRmItem* i = NULL; + FrgMenuMsg* _tmp23_ = NULL; + FrgMenuRmItem* _tmp24_ = NULL; + guint32 _tmp25_ = 0U; + gchar* _tmp26_ = NULL; + gchar* _tmp27_ = NULL; + _tmp23_ = msg; + i = (FrgMenuRmItem*) _tmp23_; + _tmp24_ = i; + _tmp25_ = (*_tmp24_).id; + _tmp26_ = g_strdup_printf ("not implemented: remove id:%u", (guint) _tmp25_); + _tmp27_ = _tmp26_; + g_debug ("foreign-menu.vala:117: %s", _tmp27_); + _g_free0 (_tmp27_); + break; + } + case FOREIGN_MENU_CLEAR: + { + SpiceCtrlMenu* _tmp28_ = NULL; + SpiceCtrlMenu* _tmp29_ = NULL; + _tmp28_ = spice_ctrl_menu_new (); + _tmp29_ = _tmp28_; + spice_ctrl_foreign_menu_set_menu (self, _tmp29_); + _g_object_unref0 (_tmp29_); + break; + } + default: + { + g_warn_if_reached (); + result = FALSE; + return result; + } + } + result = TRUE; + return result; +} + + +static void spice_ctrl_foreign_menu_handle_client_data_free (gpointer _data) { + SpiceCtrlForeignMenuHandleClientData* _data_; + _data_ = _data; + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlForeignMenuHandleClientData, _data_); +} + + +static void spice_ctrl_foreign_menu_handle_client (SpiceCtrlForeignMenu* self, GIOStream* c, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlForeignMenuHandleClientData* _data_; + SpiceCtrlForeignMenu* _tmp0_ = NULL; + GIOStream* _tmp1_ = NULL; + GIOStream* _tmp2_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlForeignMenuHandleClientData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_foreign_menu_handle_client); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_foreign_menu_handle_client_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _tmp1_ = c; + _tmp2_ = _g_object_ref0 (_tmp1_); + _g_object_unref0 (_data_->c); + _data_->c = _tmp2_; + spice_ctrl_foreign_menu_handle_client_co (_data_); +} + + +static void spice_ctrl_foreign_menu_handle_client_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error) { + SpiceCtrlForeignMenuHandleClientData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_foreign_menu_handle_client_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlForeignMenuHandleClientData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_foreign_menu_handle_client_co (_data_); +} + + +static gboolean spice_ctrl_foreign_menu_handle_client_co (SpiceCtrlForeignMenuHandleClientData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + case 2: + goto _state_2; + case 3: + goto _state_3; + case 4: + goto _state_4; + case 5: + goto _state_5; + default: + g_assert_not_reached (); + } + _state_0: + g_debug ("foreign-menu.vala:130: new socket client, reading init header"); + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = g_new0 (guint8, sizeof (FrgMenuInitHeader)); + _data_->p_length1 = 0; + _data_->_p_size_ = 0; + _data_->p = _data_->_tmp0_; + _data_->p_length1 = sizeof (FrgMenuInitHeader); + _data_->_p_size_ = _data_->p_length1; + _data_->_tmp1_ = NULL; + _data_->_tmp1__length1 = 0; + _data_->_tmp1_ = _data_->p; + _data_->_tmp1__length1 = _data_->p_length1; + _data_->header = (FrgMenuInitHeader*) _data_->_tmp1_; + _data_->_tmp2_ = NULL; + _data_->_tmp2_ = _data_->c; + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = g_io_stream_get_input_stream (_data_->_tmp2_); + _data_->_tmp4_ = NULL; + _data_->_tmp4_ = _data_->_tmp3_; + _data_->_tmp5_ = NULL; + _data_->_tmp5__length1 = 0; + _data_->_tmp5_ = _data_->p; + _data_->_tmp5__length1 = _data_->p_length1; + _data_->_state_ = 1; + spice_ctrl_input_stream_read (_data_->_tmp4_, _data_->_tmp5_, _data_->_tmp5__length1, spice_ctrl_foreign_menu_handle_client_ready, _data_); + return FALSE; + _state_1: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp6_ = NULL; + _data_->_tmp6_ = _data_->header; + _data_->_tmp7_ = 0U; + _data_->_tmp7_ = (*_data_->_tmp6_).magic; + _data_->_tmp8_ = FALSE; + _data_->_tmp8_ = g_warn_if (_data_->_tmp7_ != FOREIGN_MENU_MAGIC); + if (_data_->_tmp8_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = _data_->header; + _data_->_tmp10_ = 0U; + _data_->_tmp10_ = (*_data_->_tmp9_).version; + _data_->_tmp11_ = FALSE; + _data_->_tmp11_ = g_warn_if (_data_->_tmp10_ != ((guint32) FOREIGN_MENU_VERSION)); + if (_data_->_tmp11_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp12_ = NULL; + _data_->_tmp12_ = _data_->header; + _data_->_tmp13_ = 0U; + _data_->_tmp13_ = (*_data_->_tmp12_).size; + _data_->_tmp14_ = FALSE; + _data_->_tmp14_ = g_warn_if (((gulong) _data_->_tmp13_) < sizeof (FrgMenuInit)); + if (_data_->_tmp14_) { + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp15_ = NULL; + _data_->_tmp15_ = g_new0 (guint8, sizeof (guint64)); + _data_->cp_length1 = 0; + _data_->_cp_size_ = 0; + _data_->cp = _data_->_tmp15_; + _data_->cp_length1 = sizeof (guint64); + _data_->_cp_size_ = _data_->cp_length1; + _data_->_tmp16_ = NULL; + _data_->_tmp16_ = _data_->c; + _data_->_tmp17_ = NULL; + _data_->_tmp17_ = g_io_stream_get_input_stream (_data_->_tmp16_); + _data_->_tmp18_ = NULL; + _data_->_tmp18_ = _data_->_tmp17_; + _data_->_tmp19_ = NULL; + _data_->_tmp19__length1 = 0; + _data_->_tmp19_ = _data_->cp; + _data_->_tmp19__length1 = _data_->cp_length1; + _data_->_state_ = 2; + spice_ctrl_input_stream_read (_data_->_tmp18_, _data_->_tmp19_, _data_->_tmp19__length1, spice_ctrl_foreign_menu_handle_client_ready, _data_); + return FALSE; + _state_2: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp20_ = NULL; + _data_->_tmp20__length1 = 0; + _data_->_tmp20_ = _data_->cp; + _data_->_tmp20__length1 = _data_->cp_length1; + _data_->credentials = *((guint64*) _data_->_tmp20_); + _data_->_tmp21_ = 0ULL; + _data_->_tmp21_ = _data_->credentials; + _data_->_tmp22_ = FALSE; + _data_->_tmp22_ = g_warn_if (_data_->_tmp21_ != ((guint64) 0)); + if (_data_->_tmp22_) { + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp23_ = NULL; + _data_->_tmp23_ = _data_->header; + _data_->_tmp24_ = 0U; + _data_->_tmp24_ = (*_data_->_tmp23_).size; + _data_->title_size = _data_->_tmp24_ - sizeof (FrgMenuInit); + _data_->_tmp25_ = 0UL; + _data_->_tmp25_ = _data_->title_size; + _data_->_tmp26_ = NULL; + _data_->_tmp26_ = g_new0 (guint8, _data_->_tmp25_ + 1); + _data_->title_length1 = 0; + _data_->_title_size_ = 0; + _data_->title = _data_->_tmp26_; + _data_->title_length1 = _data_->_tmp25_ + 1; + _data_->_title_size_ = _data_->title_length1; + _data_->_tmp27_ = NULL; + _data_->_tmp27_ = _data_->c; + _data_->_tmp28_ = NULL; + _data_->_tmp28_ = g_io_stream_get_input_stream (_data_->_tmp27_); + _data_->_tmp29_ = NULL; + _data_->_tmp29_ = _data_->_tmp28_; + _data_->_tmp30_ = NULL; + _data_->_tmp30__length1 = 0; + _data_->_tmp30_ = _data_->title; + _data_->_tmp30__length1 = _data_->title_length1; + _data_->_tmp31_ = 0UL; + _data_->_tmp31_ = _data_->title_size; + _data_->_state_ = 3; + g_input_stream_read_async (_data_->_tmp29_, _data_->_tmp30_ + 0, (gsize) (((gint) _data_->_tmp31_) - 0), G_PRIORITY_DEFAULT, NULL, spice_ctrl_foreign_menu_handle_client_ready, _data_); + return FALSE; + _state_3: + g_input_stream_read_finish (_data_->_tmp29_, _data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->title = (g_free (_data_->title), NULL); + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp32_ = NULL; + _data_->_tmp32__length1 = 0; + _data_->_tmp32_ = _data_->title; + _data_->_tmp32__length1 = _data_->title_length1; + spice_ctrl_foreign_menu_set_title (_data_->self, (const gchar*) _data_->_tmp32_); + g_signal_emit_by_name (_data_->self, "client-connected"); + { + _data_->_tmp33_ = TRUE; + while (TRUE) { + if (!_data_->_tmp33_) { + } + _data_->_tmp33_ = FALSE; + _data_->_tmp34_ = NULL; + _data_->_tmp34_ = g_new0 (guint8, sizeof (FrgMenuMsg)); + _data_->t_length1 = 0; + _data_->_t_size_ = 0; + _data_->t = _data_->_tmp34_; + _data_->t_length1 = sizeof (FrgMenuMsg); + _data_->_t_size_ = _data_->t_length1; + _data_->_tmp35_ = NULL; + _data_->_tmp35_ = _data_->c; + _data_->_tmp36_ = NULL; + _data_->_tmp36_ = g_io_stream_get_input_stream (_data_->_tmp35_); + _data_->_tmp37_ = NULL; + _data_->_tmp37_ = _data_->_tmp36_; + _data_->_tmp38_ = NULL; + _data_->_tmp38__length1 = 0; + _data_->_tmp38_ = _data_->t; + _data_->_tmp38__length1 = _data_->t_length1; + _data_->_state_ = 4; + spice_ctrl_input_stream_read (_data_->_tmp37_, _data_->_tmp38_, _data_->_tmp38__length1, spice_ctrl_foreign_menu_handle_client_ready, _data_); + return FALSE; + _state_4: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->t = (g_free (_data_->t), NULL); + _data_->title = (g_free (_data_->title), NULL); + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp39_ = NULL; + _data_->_tmp39__length1 = 0; + _data_->_tmp39_ = _data_->t; + _data_->_tmp39__length1 = _data_->t_length1; + _data_->msg = (FrgMenuMsg*) _data_->_tmp39_; + _data_->_tmp40_ = NULL; + _data_->_tmp40_ = _data_->msg; + _data_->_tmp41_ = 0U; + _data_->_tmp41_ = (*_data_->_tmp40_).id; + _data_->_tmp42_ = NULL; + _data_->_tmp42_ = g_strdup_printf ("%u", _data_->_tmp41_); + _data_->_tmp43_ = NULL; + _data_->_tmp43_ = _data_->_tmp42_; + _data_->_tmp44_ = NULL; + _data_->_tmp44_ = g_strconcat ("new message ", _data_->_tmp43_, NULL); + _data_->_tmp45_ = NULL; + _data_->_tmp45_ = _data_->_tmp44_; + _data_->_tmp46_ = NULL; + _data_->_tmp46_ = g_strconcat (_data_->_tmp45_, "size ", NULL); + _data_->_tmp47_ = NULL; + _data_->_tmp47_ = _data_->_tmp46_; + _data_->_tmp48_ = NULL; + _data_->_tmp48_ = _data_->msg; + _data_->_tmp49_ = 0U; + _data_->_tmp49_ = (*_data_->_tmp48_).size; + _data_->_tmp50_ = NULL; + _data_->_tmp50_ = g_strdup_printf ("%u", _data_->_tmp49_); + _data_->_tmp51_ = NULL; + _data_->_tmp51_ = _data_->_tmp50_; + _data_->_tmp52_ = NULL; + _data_->_tmp52_ = g_strconcat (_data_->_tmp47_, _data_->_tmp51_, NULL); + _data_->_tmp53_ = NULL; + _data_->_tmp53_ = _data_->_tmp52_; + g_debug ("foreign-menu.vala:159: %s", _data_->_tmp53_); + _g_free0 (_data_->_tmp53_); + _g_free0 (_data_->_tmp51_); + _g_free0 (_data_->_tmp47_); + _g_free0 (_data_->_tmp45_); + _g_free0 (_data_->_tmp43_); + _data_->_tmp54_ = NULL; + _data_->_tmp54_ = _data_->msg; + _data_->_tmp55_ = 0U; + _data_->_tmp55_ = (*_data_->_tmp54_).size; + _data_->_tmp56_ = FALSE; + _data_->_tmp56_ = g_warn_if (((gulong) _data_->_tmp55_) < sizeof (FrgMenuMsg)); + if (_data_->_tmp56_) { + _data_->t = (g_free (_data_->t), NULL); + break; + } + _data_->_tmp57_ = NULL; + _data_->_tmp57_ = _data_->msg; + _data_->_tmp58_ = 0U; + _data_->_tmp58_ = (*_data_->_tmp57_).size; + if (((gulong) _data_->_tmp58_) > sizeof (FrgMenuMsg)) { + _data_->_tmp59_ = NULL; + _data_->_tmp59_ = _data_->msg; + _data_->_tmp60_ = 0U; + _data_->_tmp60_ = (*_data_->_tmp59_).size; + _data_->_tmp61_ = 0; + _data_->_tmp61_ = (gint) _data_->_tmp60_; + _data_->t = g_renew (guint8, _data_->t, (gint) _data_->_tmp60_); + (_data_->_tmp61_ > _data_->t_length1) ? memset (_data_->t + _data_->t_length1, 0, sizeof (guint8) * (_data_->_tmp61_ - _data_->t_length1)) : NULL; + _data_->t_length1 = _data_->_tmp61_; + _data_->_t_size_ = _data_->_tmp61_; + _data_->_tmp62_ = NULL; + _data_->_tmp62__length1 = 0; + _data_->_tmp62_ = _data_->t; + _data_->_tmp62__length1 = _data_->t_length1; + _data_->msg = (FrgMenuMsg*) _data_->_tmp62_; + _data_->_tmp63_ = NULL; + _data_->_tmp63_ = _data_->c; + _data_->_tmp64_ = NULL; + _data_->_tmp64_ = g_io_stream_get_input_stream (_data_->_tmp63_); + _data_->_tmp65_ = NULL; + _data_->_tmp65_ = _data_->_tmp64_; + _data_->_tmp66_ = NULL; + _data_->_tmp66__length1 = 0; + _data_->_tmp66_ = _data_->t; + _data_->_tmp66__length1 = _data_->t_length1; + _data_->_tmp67_ = NULL; + _data_->_tmp67_ = _data_->msg; + _data_->_tmp68_ = 0U; + _data_->_tmp68_ = (*_data_->_tmp67_).size; + _data_->_state_ = 5; + spice_ctrl_input_stream_read (_data_->_tmp65_, _data_->_tmp66_ + ((gint) sizeof (FrgMenuMsg)), ((gint) _data_->_tmp68_) - ((gint) sizeof (FrgMenuMsg)), spice_ctrl_foreign_menu_handle_client_ready, _data_); + return FALSE; + _state_5: + spice_ctrl_input_stream_read_finish (_data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->t = (g_free (_data_->t), NULL); + _data_->title = (g_free (_data_->title), NULL); + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + } + _data_->_tmp69_ = NULL; + _data_->_tmp69_ = _data_->msg; + spice_ctrl_foreign_menu_handle_message (_data_->self, _data_->_tmp69_); + _data_->t = (g_free (_data_->t), NULL); + } + } + _data_->title = (g_free (_data_->title), NULL); + _data_->cp = (g_free (_data_->cp), NULL); + _data_->p = (g_free (_data_->p), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +static void spice_ctrl_foreign_menu_listen_data_free (gpointer _data) { + SpiceCtrlForeignMenuListenData* _data_; + _data_ = _data; + _g_free0 (_data_->addr); + _g_object_unref0 (_data_->self); + g_slice_free (SpiceCtrlForeignMenuListenData, _data_); +} + + +void spice_ctrl_foreign_menu_listen (SpiceCtrlForeignMenu* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlForeignMenuListenData* _data_; + SpiceCtrlForeignMenu* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gchar* _tmp2_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlForeignMenuListenData); + _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, spice_ctrl_foreign_menu_listen); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_foreign_menu_listen_data_free); + _tmp0_ = _g_object_ref0 (self); + _data_->self = _tmp0_; + _tmp1_ = addr; + _tmp2_ = g_strdup (_tmp1_); + _g_free0 (_data_->addr); + _data_->addr = _tmp2_; + spice_ctrl_foreign_menu_listen_co (_data_); +} + + +void spice_ctrl_foreign_menu_listen_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error) { + SpiceCtrlForeignMenuListenData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_foreign_menu_listen_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlForeignMenuListenData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_foreign_menu_listen_co (_data_); +} + + +static gboolean spice_ctrl_foreign_menu_listen_co (SpiceCtrlForeignMenuListenData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + case 2: + goto _state_2; + default: + g_assert_not_reached (); + } + _state_0: + _data_->_tmp0_ = NULL; + _data_->_tmp0_ = _data_->addr; + _data_->_tmp1_ = NULL; + _data_->_tmp1_ = spice_foreign_menu_listener_new (_data_->_tmp0_, &_data_->_inner_error_); + _data_->listener = _data_->_tmp1_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + { + _data_->_tmp2_ = TRUE; + while (TRUE) { + if (!_data_->_tmp2_) { + } + _data_->_tmp2_ = FALSE; + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = _data_->listener; + _data_->_state_ = 1; + spice_foreign_menu_listener_accept_async (_data_->_tmp3_, NULL, spice_ctrl_foreign_menu_listen_ready, _data_); + return FALSE; + _state_1: + _data_->_tmp4_ = NULL; + _data_->_tmp4_ = spice_foreign_menu_listener_accept_finish (_data_->_tmp3_, _data_->_res_, NULL, &_data_->_inner_error_); + _data_->_tmp5_ = NULL; + _data_->_tmp5_ = _g_object_ref0 (_data_->_tmp4_); + _data_->c = _data_->_tmp5_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp6_ = 0; + _data_->_tmp6_ = _data_->self->priv->nclients; + _data_->self->priv->nclients = _data_->_tmp6_ + 1; + _data_->_tmp7_ = NULL; + _data_->_tmp7_ = _data_->c; + _data_->_tmp8_ = NULL; + _data_->_tmp8_ = _g_object_ref0 (_data_->_tmp7_); + _data_->self->priv->clients = g_list_append (_data_->self->priv->clients, _data_->_tmp8_); + { + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = _data_->c; + _data_->_state_ = 2; + spice_ctrl_foreign_menu_handle_client (_data_->self, _data_->_tmp9_, spice_ctrl_foreign_menu_listen_ready, _data_); + return FALSE; + _state_2: + spice_ctrl_foreign_menu_handle_client_finish (_data_->self, _data_->_res_, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + goto __catch4_g_error; + } + } + goto __finally4; + __catch4_g_error: + { + _data_->e = _data_->_inner_error_; + _data_->_inner_error_ = NULL; + _data_->_tmp10_ = NULL; + _data_->_tmp10_ = _data_->e; + _data_->_tmp11_ = NULL; + _data_->_tmp11_ = _data_->_tmp10_->message; + g_warning ("foreign-menu.vala:187: %s", _data_->_tmp11_); + _g_error_free0 (_data_->e); + } + __finally4: + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp12_ = NULL; + _data_->_tmp12_ = _data_->c; + g_io_stream_close (_data_->_tmp12_, NULL, &_data_->_inner_error_); + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _g_object_unref0 (_data_->c); + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } + _data_->_tmp13_ = NULL; + _data_->_tmp13_ = _data_->c; + _data_->self->priv->clients = g_list_remove (_data_->self->priv->clients, _data_->_tmp13_); + _data_->_tmp14_ = 0; + _data_->_tmp14_ = _data_->self->priv->nclients; + _data_->self->priv->nclients = _data_->_tmp14_ - 1; + _g_object_unref0 (_data_->c); + } + } + _g_object_unref0 (_data_->listener); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +SpiceCtrlMenu* spice_ctrl_foreign_menu_get_menu (SpiceCtrlForeignMenu* self) { + SpiceCtrlMenu* result; + SpiceCtrlMenu* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_menu; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_foreign_menu_set_menu (SpiceCtrlForeignMenu* self, SpiceCtrlMenu* value) { + SpiceCtrlMenu* _tmp0_ = NULL; + SpiceCtrlMenu* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = _g_object_ref0 (_tmp0_); + _g_object_unref0 (self->priv->_menu); + self->priv->_menu = _tmp1_; + g_object_notify ((GObject *) self, "menu"); +} + + +const gchar* spice_ctrl_foreign_menu_get_title (SpiceCtrlForeignMenu* self) { + const gchar* result; + const gchar* _tmp0_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->priv->_title; + result = _tmp0_; + return result; +} + + +static void spice_ctrl_foreign_menu_set_title (SpiceCtrlForeignMenu* self, const gchar* value) { + const gchar* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + g_return_if_fail (self != NULL); + _tmp0_ = value; + _tmp1_ = g_strdup (_tmp0_); + _g_free0 (self->priv->_title); + self->priv->_title = _tmp1_; + g_object_notify ((GObject *) self, "title"); +} + + +static void spice_ctrl_foreign_menu_class_init (SpiceCtrlForeignMenuClass * klass) { + spice_ctrl_foreign_menu_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (SpiceCtrlForeignMenuPrivate)); + G_OBJECT_CLASS (klass)->get_property = _vala_spice_ctrl_foreign_menu_get_property; + G_OBJECT_CLASS (klass)->set_property = _vala_spice_ctrl_foreign_menu_set_property; + G_OBJECT_CLASS (klass)->finalize = spice_ctrl_foreign_menu_finalize; + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_FOREIGN_MENU_MENU, g_param_spec_object ("menu", "menu", "menu", SPICE_CTRL_TYPE_MENU, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), SPICE_CTRL_FOREIGN_MENU_TITLE, g_param_spec_string ("title", "title", "title", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE)); + g_signal_new ("client_connected", SPICE_CTRL_TYPE_FOREIGN_MENU, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +} + + +static void spice_ctrl_foreign_menu_instance_init (SpiceCtrlForeignMenu * self) { + self->priv = SPICE_CTRL_FOREIGN_MENU_GET_PRIVATE (self); +} + + +static void spice_ctrl_foreign_menu_finalize (GObject* obj) { + SpiceCtrlForeignMenu * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenu); + _g_object_unref0 (self->priv->_menu); + _g_free0 (self->priv->_title); + __g_list_free__g_object_unref0_0 (self->priv->clients); + G_OBJECT_CLASS (spice_ctrl_foreign_menu_parent_class)->finalize (obj); +} + + +GType spice_ctrl_foreign_menu_get_type (void) { + static volatile gsize spice_ctrl_foreign_menu_type_id__volatile = 0; + if (g_once_init_enter (&spice_ctrl_foreign_menu_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (SpiceCtrlForeignMenuClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) spice_ctrl_foreign_menu_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SpiceCtrlForeignMenu), 0, (GInstanceInitFunc) spice_ctrl_foreign_menu_instance_init, NULL }; + GType spice_ctrl_foreign_menu_type_id; + spice_ctrl_foreign_menu_type_id = g_type_register_static (G_TYPE_OBJECT, "SpiceCtrlForeignMenu", &g_define_type_info, 0); + g_once_init_leave (&spice_ctrl_foreign_menu_type_id__volatile, spice_ctrl_foreign_menu_type_id); + } + return spice_ctrl_foreign_menu_type_id__volatile; +} + + +static void _vala_spice_ctrl_foreign_menu_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { + SpiceCtrlForeignMenu * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenu); + switch (property_id) { + case SPICE_CTRL_FOREIGN_MENU_MENU: + g_value_set_object (value, spice_ctrl_foreign_menu_get_menu (self)); + break; + case SPICE_CTRL_FOREIGN_MENU_TITLE: + g_value_set_string (value, spice_ctrl_foreign_menu_get_title (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void _vala_spice_ctrl_foreign_menu_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { + SpiceCtrlForeignMenu * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenu); + switch (property_id) { + case SPICE_CTRL_FOREIGN_MENU_MENU: + spice_ctrl_foreign_menu_set_menu (self, g_value_get_object (value)); + break; + case SPICE_CTRL_FOREIGN_MENU_TITLE: + spice_ctrl_foreign_menu_set_title (self, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + + diff --git a/src/controller/foreign-menu.vala b/src/controller/foreign-menu.vala new file mode 100644 index 0000000..005955a --- /dev/null +++ b/src/controller/foreign-menu.vala @@ -0,0 +1,197 @@ +// Copyright (C) 2012 Red Hat, Inc. + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . + +using Custom; + +namespace SpiceCtrl { + +public class ForeignMenu: Object { + + public Menu menu { get; private set; } + public string title { get; private set; } + + public signal void client_connected (); + + private int nclients; + private List clients; + + public ForeignMenu() { + menu = new Menu (); + } + + public void menu_item_click_msg (int32 item_id) { + debug ("clicked id: %d".printf (item_id)); + + var msg = SpiceProtocol.ForeignMenu.Event (); + msg.base.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event); + msg.base.id = SpiceProtocol.ForeignMenu.MsgId.ITEM_EVENT; + msg.id = item_id; + msg.action = SpiceProtocol.ForeignMenu.EventType.CLICK; + + unowned uint8[] p = ((uint8[])(&msg))[0:msg.base.size]; + send_msg.begin (p); + } + + public void menu_item_checked_msg (int32 item_id, bool checked = true) { + debug ("%schecked id: %d".printf (checked ? "" : "un", item_id)); + + var msg = SpiceProtocol.ForeignMenu.Event (); + msg.base.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event); + msg.base.id = SpiceProtocol.ForeignMenu.MsgId.ITEM_EVENT; + msg.id = item_id; + msg.action = checked ? + SpiceProtocol.ForeignMenu.EventType.CHECKED : + SpiceProtocol.ForeignMenu.EventType.UNCHECKED; + + unowned uint8[] p = ((uint8[])(&msg))[0:msg.base.size]; + send_msg.begin (p); + } + + public void app_activated_msg (bool activated = true) { + var msg = SpiceProtocol.ForeignMenu.Msg (); + msg.size = (uint32)sizeof (SpiceProtocol.ForeignMenu.Event); + msg.id = activated ? + SpiceProtocol.ForeignMenu.MsgId.APP_ACTIVATED : + SpiceProtocol.ForeignMenu.MsgId.APP_DEACTIVATED; + + unowned uint8[] p = ((uint8[])(&msg))[0:msg.size]; + send_msg.begin (p); + } + + public async bool send_msg (owned uint8[] p) throws GLib.Error { + // vala FIXME: pass Controller.Msg instead + // vala doesn't keep reference on the struct in async methods + // it copies only base, which is not enough to transmit the whole + // message. + try { + foreach (var c in clients) { + yield output_stream_write (c.output_stream, p); + } + } catch (GLib.Error e) { + warning (e.message); + } + + return true; + } + + SpiceProtocol.Controller.MenuFlags get_menu_flags (uint32 type) { + SpiceProtocol.Controller.MenuFlags flags = 0; + + if ((SpiceProtocol.ForeignMenu.MenuFlags.CHECKED & type) != 0) + flags |= SpiceProtocol.Controller.MenuFlags.CHECKED; + if ((SpiceProtocol.ForeignMenu.MenuFlags.DIM & type) != 0) + flags |= SpiceProtocol.Controller.MenuFlags.GRAYED; + + return flags; + } + + private bool handle_message (SpiceProtocol.ForeignMenu.Msg* msg) { + switch (msg.id) { + case SpiceProtocol.ForeignMenu.MsgId.SET_TITLE: + var t = (SpiceProtocol.ForeignMenu.SetTitle*)(msg); + title = t.string; + break; + case SpiceProtocol.ForeignMenu.MsgId.ADD_ITEM: + var i = (SpiceProtocol.ForeignMenu.AddItem*)(msg); + debug ("add id:%u type:%u position:%u title:%s", i.id, i.type, i.position, i.string); + menu.items.append (new MenuItem ((int)i.id, i.string, get_menu_flags (i.type))); + notify_property ("menu"); + break; + case SpiceProtocol.ForeignMenu.MsgId.MODIFY_ITEM: + debug ("deprecated: modify item"); + break; + case SpiceProtocol.ForeignMenu.MsgId.REMOVE_ITEM: + var i = (SpiceProtocol.ForeignMenu.RmItem*)(msg); + debug ("not implemented: remove id:%u".printf (i.id)); + break; + case SpiceProtocol.ForeignMenu.MsgId.CLEAR: + menu = new Menu (); + break; + default: + warn_if_reached (); + return false; + } + return true; + } + + private async void handle_client (IOStream c) throws GLib.Error { + debug ("new socket client, reading init header"); + + var p = new uint8[sizeof(SpiceProtocol.ForeignMenu.InitHeader)]; + var header = (SpiceProtocol.ForeignMenu.InitHeader*)p; + yield input_stream_read (c.input_stream, p); + if (warn_if (header.magic != SpiceProtocol.ForeignMenu.MAGIC)) + return; + if (warn_if (header.version != SpiceProtocol.ForeignMenu.VERSION)) + return; + if (warn_if (header.size < sizeof (SpiceProtocol.ForeignMenu.Init))) + return; + + var cp = new uint8[sizeof(uint64)]; + yield input_stream_read (c.input_stream, cp); + uint64 credentials = *(uint64*)cp; + if (warn_if (credentials != 0)) + return; + + var title_size = header.size - sizeof(SpiceProtocol.ForeignMenu.Init); + var title = new uint8[title_size + 1]; + yield c.input_stream.read_async (title[0:title_size]); + this.title = (string)title; + + client_connected (); + + for (;;) { + var t = new uint8[sizeof(SpiceProtocol.ForeignMenu.Msg)]; + yield input_stream_read (c.input_stream, t); + var msg = (SpiceProtocol.ForeignMenu.Msg*)t; + debug ("new message " + msg.id.to_string () + "size " + msg.size.to_string ()); + + if (warn_if (msg.size < sizeof (SpiceProtocol.ForeignMenu.Msg))) + break; + + if (msg.size > sizeof (SpiceProtocol.ForeignMenu.Msg)) { + t.resize ((int)msg.size); + msg = (SpiceProtocol.ForeignMenu.Msg*)t; + + yield input_stream_read (c.input_stream, t[sizeof(SpiceProtocol.ForeignMenu.Msg):msg.size]); + } + + handle_message (msg); + } + + } + + public async void listen (string? addr = null) throws GLib.Error, SpiceCtrl.Error + { + var listener = Spice.ForeignMenuListener.new_listener (addr); + + for (;;) { + var c = yield listener.accept_async (); + nclients += 1; + clients.append (c); + try { + yield handle_client (c); + } catch (GLib.Error e) { + warning (e.message); + } + c.close (); + clients.remove (c); + nclients -= 1; + } + } + +} + +} // SpiceCtrl diff --git a/src/controller/gio-windows-2.0.vapi b/src/controller/gio-windows-2.0.vapi new file mode 100644 index 0000000..a09cfe8 --- /dev/null +++ b/src/controller/gio-windows-2.0.vapi @@ -0,0 +1,30 @@ +/* gio-windows-2.0.vapi generated by vapigen. */ +/* NOT YET UPSTREAM: https://bugzilla.gnome.org/show_bug.cgi?id=650052 */ + +[CCode (cprefix = "GLib", lower_case_cprefix = "glib_")] +namespace GLib { + [CCode (cheader_filename = "gio/gwin32inputstream.h")] + public class Win32InputStream : GLib.InputStream { + public weak GLib.InputStream parent_instance; + [CCode (cname = "g_win32_input_stream_new", type = "GInputStream*", has_construct_function = false)] + public Win32InputStream (void* handle, bool close_handle); + [CCode (cname = "g_win32_input_stream_get_close_handle")] + public static bool get_close_handle (GLib.Win32InputStream stream); + [CCode (cname = "g_win32_input_stream_get_handle")] + public static void* get_handle (GLib.Win32InputStream stream); + [CCode (cname = "g_win32_input_stream_set_close_handle")] + public static void set_close_handle (GLib.Win32InputStream stream, bool close_handle); + } + [CCode (cheader_filename = "gio/gwin32inputstream.h")] + public class Win32OutputStream : GLib.OutputStream { + public weak GLib.OutputStream parent_instance; + [CCode (cname = "g_win32_output_stream_new", type = "GOutputStream*", has_construct_function = false)] + public Win32OutputStream (void* handle, bool close_handle); + [CCode (cname = "g_win32_output_stream_get_close_handle")] + public static bool get_close_handle (GLib.Win32OutputStream stream); + [CCode (cname = "g_win32_output_stream_get_handle")] + public static void* get_handle (GLib.Win32OutputStream stream); + [CCode (cname = "g_win32_output_stream_set_close_handle")] + public static void set_close_handle (GLib.Win32OutputStream stream, bool close_handle); + } +} diff --git a/src/controller/menu.c b/src/controller/menu.c new file mode 100644 index 0000000..02b9163 --- /dev/null +++ b/src/controller/menu.c @@ -0,0 +1,733 @@ +/* menu.c generated by valac 0.32.0, the Vala compiler + * generated from menu.vala, do not modify */ + +/* Copyright (C) 2011 Red Hat, Inc.*/ +/* This library is free software; you can redistribute it and/or*/ +/* modify it under the terms of the GNU Lesser General Public*/ +/* License as published by the Free Software Foundation; either*/ +/* version 2.1 of the License, or (at your option) any later version.*/ +/* This library is distributed in the hope that it will be useful,*/ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of*/ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU*/ +/* Lesser General Public License for more details.*/ +/* You should have received a copy of the GNU Lesser General Public*/ +/* License along with this library; if not, see .*/ + +#include +#include +#include +#include +#include +#include + + +#define SPICE_CTRL_TYPE_MENU_ITEM (spice_ctrl_menu_item_get_type ()) +#define SPICE_CTRL_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItem)) +#define SPICE_CTRL_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) +#define SPICE_CTRL_IS_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) + +typedef struct _SpiceCtrlMenuItem SpiceCtrlMenuItem; +typedef struct _SpiceCtrlMenuItemClass SpiceCtrlMenuItemClass; +typedef struct _SpiceCtrlMenuItemPrivate SpiceCtrlMenuItemPrivate; + +#define SPICE_CTRL_TYPE_MENU (spice_ctrl_menu_get_type ()) +#define SPICE_CTRL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenu)) +#define SPICE_CTRL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) +#define SPICE_CTRL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) + +typedef struct _SpiceCtrlMenu SpiceCtrlMenu; +typedef struct _SpiceCtrlMenuClass SpiceCtrlMenuClass; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +typedef struct _SpiceCtrlMenuPrivate SpiceCtrlMenuPrivate; +#define __g_list_free__g_object_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__g_object_unref0_ (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) + +struct _SpiceCtrlMenuItem { + GObject parent_instance; + SpiceCtrlMenuItemPrivate * priv; + SpiceCtrlMenu* submenu; + gint parent_id; + gint id; + gchar* text; + gchar* accel; + unsigned int flags; +}; + +struct _SpiceCtrlMenuItemClass { + GObjectClass parent_class; +}; + +typedef enum { + SPICE_CTRL_ERROR_VALUE +} SpiceCtrlError; +#define SPICE_CTRL_ERROR spice_ctrl_error_quark () +struct _SpiceCtrlMenu { + GObject parent_instance; + SpiceCtrlMenuPrivate * priv; + GList* items; +}; + +struct _SpiceCtrlMenuClass { + GObjectClass parent_class; +}; + + +static gpointer spice_ctrl_menu_item_parent_class = NULL; +static gpointer spice_ctrl_menu_parent_class = NULL; + +GType spice_ctrl_menu_item_get_type (void) G_GNUC_CONST; +GType spice_ctrl_menu_get_type (void) G_GNUC_CONST; +enum { + SPICE_CTRL_MENU_ITEM_DUMMY_PROPERTY +}; +SpiceCtrlMenuItem* spice_ctrl_menu_item_new (gint id, const gchar* text, unsigned int flags); +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct (GType object_type, gint id, const gchar* text, unsigned int flags); +GQuark spice_ctrl_error_quark (void); +SpiceCtrlMenuItem* spice_ctrl_menu_item_new_from_string (const gchar* str, GError** error); +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct_from_string (GType object_type, const gchar* str, GError** error); +SpiceCtrlMenu* spice_ctrl_menu_new (void); +SpiceCtrlMenu* spice_ctrl_menu_construct (GType object_type); +gchar* spice_ctrl_menu_item_to_string (SpiceCtrlMenuItem* self); +gchar* spice_ctrl_menu_to_string (SpiceCtrlMenu* self); +const gchar* spice_protocol_controller_menu_flags_to_string (unsigned int self); +static const char* _spice_protocol_controller_menu_flags_to_string (unsigned int value); +static void spice_ctrl_menu_item_finalize (GObject* obj); +enum { + SPICE_CTRL_MENU_DUMMY_PROPERTY +}; +static void _g_object_unref0_ (gpointer var); +static void _g_list_free__g_object_unref0_ (GList* self); +SpiceCtrlMenu* spice_ctrl_menu_find_id (SpiceCtrlMenu* self, gint id); +SpiceCtrlMenu* spice_ctrl_menu_new_from_string (const gchar* str); +SpiceCtrlMenu* spice_ctrl_menu_construct_from_string (GType object_type, const gchar* str); +static void spice_ctrl_menu_finalize (GObject* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); +static gint _vala_array_length (gpointer array); + + +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct (GType object_type, gint id, const gchar* text, unsigned int flags) { + SpiceCtrlMenuItem * self = NULL; + gint _tmp0_ = 0; + const gchar* _tmp1_ = NULL; + gchar* _tmp2_ = NULL; + unsigned int _tmp3_ = 0; + g_return_val_if_fail (text != NULL, NULL); + self = (SpiceCtrlMenuItem*) g_object_new (object_type, NULL); + _tmp0_ = id; + self->id = _tmp0_; + _tmp1_ = text; + _tmp2_ = g_strdup (_tmp1_); + _g_free0 (self->text); + self->text = _tmp2_; + _tmp3_ = flags; + self->flags = _tmp3_; + return self; +} + + +SpiceCtrlMenuItem* spice_ctrl_menu_item_new (gint id, const gchar* text, unsigned int flags) { + return spice_ctrl_menu_item_construct (SPICE_CTRL_TYPE_MENU_ITEM, id, text, flags); +} + + +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct_from_string (GType object_type, const gchar* str, GError** error) { + SpiceCtrlMenuItem * self = NULL; + gchar** params = NULL; + const gchar* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gchar** _tmp2_ = NULL; + gchar** _tmp3_ = NULL; + gint params_length1 = 0; + gint _params_size_ = 0; + gchar** _tmp4_ = NULL; + gint _tmp4__length1 = 0; + gboolean _tmp5_ = FALSE; + gchar** _tmp7_ = NULL; + gint _tmp7__length1 = 0; + const gchar* _tmp8_ = NULL; + gint _tmp9_ = 0; + gchar** _tmp10_ = NULL; + gint _tmp10__length1 = 0; + const gchar* _tmp11_ = NULL; + gint _tmp12_ = 0; + gchar** textaccel = NULL; + gchar** _tmp13_ = NULL; + gint _tmp13__length1 = 0; + const gchar* _tmp14_ = NULL; + gchar** _tmp15_ = NULL; + gchar** _tmp16_ = NULL; + gint textaccel_length1 = 0; + gint _textaccel_size_ = 0; + gchar** _tmp17_ = NULL; + gint _tmp17__length1 = 0; + const gchar* _tmp18_ = NULL; + gchar* _tmp19_ = NULL; + gchar** _tmp20_ = NULL; + gint _tmp20__length1 = 0; + gchar** _tmp24_ = NULL; + gint _tmp24__length1 = 0; + const gchar* _tmp25_ = NULL; + gint _tmp26_ = 0; + SpiceCtrlMenu* _tmp27_ = NULL; + GError * _inner_error_ = NULL; + g_return_val_if_fail (str != NULL, NULL); + self = (SpiceCtrlMenuItem*) g_object_new (object_type, NULL); + _tmp0_ = str; + _tmp1_ = CONTROLLER_MENU_PARAM_DELIMITER; + _tmp3_ = _tmp2_ = g_strsplit (_tmp0_, _tmp1_, 0); + params = _tmp3_; + params_length1 = _vala_array_length (_tmp2_); + _params_size_ = params_length1; + _tmp4_ = params; + _tmp4__length1 = params_length1; + _tmp5_ = g_warn_if (_tmp4__length1 != 5); + if (_tmp5_) { + GError* _tmp6_ = NULL; + _tmp6_ = g_error_new_literal (SPICE_CTRL_ERROR, SPICE_CTRL_ERROR_VALUE, ""); + _inner_error_ = _tmp6_; + if (_inner_error_->domain == SPICE_CTRL_ERROR) { + g_propagate_error (error, _inner_error_); + params = (_vala_array_free (params, params_length1, (GDestroyNotify) g_free), NULL); + _g_object_unref0 (self); + return NULL; + } else { + params = (_vala_array_free (params, params_length1, (GDestroyNotify) g_free), NULL); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + } + _tmp7_ = params; + _tmp7__length1 = params_length1; + _tmp8_ = _tmp7_[0]; + _tmp9_ = atoi (_tmp8_); + self->parent_id = _tmp9_; + _tmp10_ = params; + _tmp10__length1 = params_length1; + _tmp11_ = _tmp10_[1]; + _tmp12_ = atoi (_tmp11_); + self->id = _tmp12_; + _tmp13_ = params; + _tmp13__length1 = params_length1; + _tmp14_ = _tmp13_[2]; + _tmp16_ = _tmp15_ = g_strsplit (_tmp14_, "\t", 0); + textaccel = _tmp16_; + textaccel_length1 = _vala_array_length (_tmp15_); + _textaccel_size_ = textaccel_length1; + _tmp17_ = textaccel; + _tmp17__length1 = textaccel_length1; + _tmp18_ = _tmp17_[0]; + _tmp19_ = g_strdup (_tmp18_); + _g_free0 (self->text); + self->text = _tmp19_; + _tmp20_ = textaccel; + _tmp20__length1 = textaccel_length1; + if (_tmp20__length1 > 1) { + gchar** _tmp21_ = NULL; + gint _tmp21__length1 = 0; + const gchar* _tmp22_ = NULL; + gchar* _tmp23_ = NULL; + _tmp21_ = textaccel; + _tmp21__length1 = textaccel_length1; + _tmp22_ = _tmp21_[1]; + _tmp23_ = g_strdup (_tmp22_); + _g_free0 (self->accel); + self->accel = _tmp23_; + } + _tmp24_ = params; + _tmp24__length1 = params_length1; + _tmp25_ = _tmp24_[3]; + _tmp26_ = atoi (_tmp25_); + self->flags = (unsigned int) _tmp26_; + _tmp27_ = spice_ctrl_menu_new (); + _g_object_unref0 (self->submenu); + self->submenu = _tmp27_; + textaccel = (_vala_array_free (textaccel, textaccel_length1, (GDestroyNotify) g_free), NULL); + params = (_vala_array_free (params, params_length1, (GDestroyNotify) g_free), NULL); + return self; +} + + +SpiceCtrlMenuItem* spice_ctrl_menu_item_new_from_string (const gchar* str, GError** error) { + return spice_ctrl_menu_item_construct_from_string (SPICE_CTRL_TYPE_MENU_ITEM, str, error); +} + + +static const gchar* string_to_string (const gchar* self) { + const gchar* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + result = self; + return result; +} + + +static const char* _spice_protocol_controller_menu_flags_to_string (unsigned int value) { + switch (value) { + case CONTROLLER_MENU_FLAGS_SEPARATOR: + return "CONTROLLER_MENU_FLAGS_SEPARATOR"; + case CONTROLLER_MENU_FLAGS_DISABLED: + return "CONTROLLER_MENU_FLAGS_DISABLED"; + case CONTROLLER_MENU_FLAGS_POPUP: + return "CONTROLLER_MENU_FLAGS_POPUP"; + case CONTROLLER_MENU_FLAGS_CHECKED: + return "CONTROLLER_MENU_FLAGS_CHECKED"; + case CONTROLLER_MENU_FLAGS_GRAYED: + return "CONTROLLER_MENU_FLAGS_GRAYED"; + } + return NULL; +} + + +gchar* spice_ctrl_menu_item_to_string (SpiceCtrlMenuItem* self) { + gchar* result = NULL; + gchar* sub = NULL; + SpiceCtrlMenu* _tmp0_ = NULL; + gchar* _tmp1_ = NULL; + gchar* str = NULL; + gint _tmp2_ = 0; + gchar* _tmp3_ = NULL; + gchar* _tmp4_ = NULL; + gint _tmp5_ = 0; + gchar* _tmp6_ = NULL; + gchar* _tmp7_ = NULL; + const gchar* _tmp8_ = NULL; + const gchar* _tmp9_ = NULL; + unsigned int _tmp10_ = 0; + const gchar* _tmp11_ = NULL; + gchar* _tmp12_ = NULL; + gchar* _tmp13_ = NULL; + const gchar* _tmp14_ = NULL; + const gchar* _tmp15_ = NULL; + gchar** _tmp16_ = NULL; + gchar** _tmp17_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = self->submenu; + _tmp1_ = spice_ctrl_menu_to_string (_tmp0_); + sub = _tmp1_; + _tmp2_ = self->parent_id; + _tmp3_ = g_strdup_printf ("%i", _tmp2_); + _tmp4_ = _tmp3_; + _tmp5_ = self->id; + _tmp6_ = g_strdup_printf ("%i", _tmp5_); + _tmp7_ = _tmp6_; + _tmp8_ = self->text; + _tmp9_ = string_to_string (_tmp8_); + _tmp10_ = self->flags; + _tmp11_ = _spice_protocol_controller_menu_flags_to_string (_tmp10_); + _tmp12_ = g_strconcat ("pid: ", _tmp4_, ", id: ", _tmp7_, ", text: \"", _tmp9_, "\", flags: ", _tmp11_, NULL); + _tmp13_ = _tmp12_; + _g_free0 (_tmp7_); + _g_free0 (_tmp4_); + str = _tmp13_; + _tmp14_ = sub; + _tmp15_ = string_to_string (_tmp14_); + _tmp17_ = _tmp16_ = g_strsplit (_tmp15_, "\n", 0); + { + gchar** l_collection = NULL; + gint l_collection_length1 = 0; + gint _l_collection_size_ = 0; + gint l_it = 0; + l_collection = _tmp17_; + l_collection_length1 = _vala_array_length (_tmp16_); + for (l_it = 0; l_it < _vala_array_length (_tmp16_); l_it = l_it + 1) { + gchar* _tmp18_ = NULL; + gchar* l = NULL; + _tmp18_ = g_strdup (l_collection[l_it]); + l = _tmp18_; + { + const gchar* _tmp19_ = NULL; + const gchar* _tmp20_ = NULL; + const gchar* _tmp21_ = NULL; + const gchar* _tmp22_ = NULL; + gchar* _tmp23_ = NULL; + gchar* _tmp24_ = NULL; + gchar* _tmp25_ = NULL; + _tmp19_ = l; + if (g_strcmp0 (_tmp19_, "") == 0) { + _g_free0 (l); + continue; + } + _tmp20_ = str; + _tmp21_ = l; + _tmp22_ = string_to_string (_tmp21_); + _tmp23_ = g_strconcat ("\n ", _tmp22_, NULL); + _tmp24_ = _tmp23_; + _tmp25_ = g_strconcat (_tmp20_, _tmp24_, NULL); + _g_free0 (str); + str = _tmp25_; + _g_free0 (_tmp24_); + _g_free0 (l); + } + } + l_collection = (_vala_array_free (l_collection, l_collection_length1, (GDestroyNotify) g_free), NULL); + } + result = str; + _g_free0 (sub); + return result; +} + + +static void spice_ctrl_menu_item_class_init (SpiceCtrlMenuItemClass * klass) { + spice_ctrl_menu_item_parent_class = g_type_class_peek_parent (klass); + G_OBJECT_CLASS (klass)->finalize = spice_ctrl_menu_item_finalize; +} + + +static void spice_ctrl_menu_item_instance_init (SpiceCtrlMenuItem * self) { +} + + +static void spice_ctrl_menu_item_finalize (GObject* obj) { + SpiceCtrlMenuItem * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItem); + _g_object_unref0 (self->submenu); + _g_free0 (self->text); + _g_free0 (self->accel); + G_OBJECT_CLASS (spice_ctrl_menu_item_parent_class)->finalize (obj); +} + + +GType spice_ctrl_menu_item_get_type (void) { + static volatile gsize spice_ctrl_menu_item_type_id__volatile = 0; + if (g_once_init_enter (&spice_ctrl_menu_item_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (SpiceCtrlMenuItemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) spice_ctrl_menu_item_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SpiceCtrlMenuItem), 0, (GInstanceInitFunc) spice_ctrl_menu_item_instance_init, NULL }; + GType spice_ctrl_menu_item_type_id; + spice_ctrl_menu_item_type_id = g_type_register_static (G_TYPE_OBJECT, "SpiceCtrlMenuItem", &g_define_type_info, 0); + g_once_init_leave (&spice_ctrl_menu_item_type_id__volatile, spice_ctrl_menu_item_type_id); + } + return spice_ctrl_menu_item_type_id__volatile; +} + + +static void _g_object_unref0_ (gpointer var) { + (var == NULL) ? NULL : (var = (g_object_unref (var), NULL)); +} + + +static void _g_list_free__g_object_unref0_ (GList* self) { + g_list_foreach (self, (GFunc) _g_object_unref0_, NULL); + g_list_free (self); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +SpiceCtrlMenu* spice_ctrl_menu_find_id (SpiceCtrlMenu* self, gint id) { + SpiceCtrlMenu* result = NULL; + gint _tmp0_ = 0; + GList* _tmp2_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = id; + if (_tmp0_ == 0) { + SpiceCtrlMenu* _tmp1_ = NULL; + _tmp1_ = _g_object_ref0 (self); + result = _tmp1_; + return result; + } + _tmp2_ = self->items; + { + GList* item_collection = NULL; + GList* item_it = NULL; + item_collection = _tmp2_; + for (item_it = item_collection; item_it != NULL; item_it = item_it->next) { + SpiceCtrlMenuItem* _tmp3_ = NULL; + SpiceCtrlMenuItem* item = NULL; + _tmp3_ = _g_object_ref0 ((SpiceCtrlMenuItem*) item_it->data); + item = _tmp3_; + { + SpiceCtrlMenuItem* _tmp4_ = NULL; + gint _tmp5_ = 0; + gint _tmp6_ = 0; + SpiceCtrlMenu* menu = NULL; + SpiceCtrlMenuItem* _tmp10_ = NULL; + SpiceCtrlMenu* _tmp11_ = NULL; + gint _tmp12_ = 0; + SpiceCtrlMenu* _tmp13_ = NULL; + SpiceCtrlMenu* _tmp14_ = NULL; + _tmp4_ = item; + _tmp5_ = _tmp4_->id; + _tmp6_ = id; + if (_tmp5_ == _tmp6_) { + SpiceCtrlMenuItem* _tmp7_ = NULL; + SpiceCtrlMenu* _tmp8_ = NULL; + SpiceCtrlMenu* _tmp9_ = NULL; + _tmp7_ = item; + _tmp8_ = _tmp7_->submenu; + _tmp9_ = _g_object_ref0 (_tmp8_); + result = _tmp9_; + _g_object_unref0 (item); + return result; + } + _tmp10_ = item; + _tmp11_ = _tmp10_->submenu; + _tmp12_ = id; + _tmp13_ = spice_ctrl_menu_find_id (_tmp11_, _tmp12_); + menu = _tmp13_; + _tmp14_ = menu; + if (_tmp14_ != NULL) { + result = menu; + _g_object_unref0 (item); + return result; + } + _g_object_unref0 (menu); + _g_object_unref0 (item); + } + } + } + result = NULL; + return result; +} + + +SpiceCtrlMenu* spice_ctrl_menu_construct_from_string (GType object_type, const gchar* str) { + SpiceCtrlMenu * self = NULL; + const gchar* _tmp0_ = NULL; + const gchar* _tmp1_ = NULL; + gchar** _tmp2_ = NULL; + gchar** _tmp3_ = NULL; + GError * _inner_error_ = NULL; + g_return_val_if_fail (str != NULL, NULL); + self = (SpiceCtrlMenu*) g_object_new (object_type, NULL); + _tmp0_ = str; + _tmp1_ = CONTROLLER_MENU_ITEM_DELIMITER; + _tmp3_ = _tmp2_ = g_strsplit (_tmp0_, _tmp1_, 0); + { + gchar** itemstr_collection = NULL; + gint itemstr_collection_length1 = 0; + gint _itemstr_collection_size_ = 0; + gint itemstr_it = 0; + itemstr_collection = _tmp3_; + itemstr_collection_length1 = _vala_array_length (_tmp2_); + for (itemstr_it = 0; itemstr_it < _vala_array_length (_tmp2_); itemstr_it = itemstr_it + 1) { + gchar* _tmp4_ = NULL; + gchar* itemstr = NULL; + _tmp4_ = g_strdup (itemstr_collection[itemstr_it]); + itemstr = _tmp4_; + { + { + const gchar* _tmp5_ = NULL; + gint _tmp6_ = 0; + gint _tmp7_ = 0; + SpiceCtrlMenuItem* item = NULL; + const gchar* _tmp8_ = NULL; + SpiceCtrlMenuItem* _tmp9_ = NULL; + SpiceCtrlMenu* parent = NULL; + SpiceCtrlMenuItem* _tmp10_ = NULL; + gint _tmp11_ = 0; + SpiceCtrlMenu* _tmp12_ = NULL; + SpiceCtrlMenu* _tmp13_ = NULL; + SpiceCtrlMenu* _tmp15_ = NULL; + SpiceCtrlMenuItem* _tmp16_ = NULL; + SpiceCtrlMenuItem* _tmp17_ = NULL; + _tmp5_ = itemstr; + _tmp6_ = strlen (_tmp5_); + _tmp7_ = _tmp6_; + if (_tmp7_ == 0) { + _g_free0 (itemstr); + continue; + } + _tmp8_ = itemstr; + _tmp9_ = spice_ctrl_menu_item_new_from_string (_tmp8_, &_inner_error_); + item = _tmp9_; + if (G_UNLIKELY (_inner_error_ != NULL)) { + if (_inner_error_->domain == SPICE_CTRL_ERROR) { + goto __catch0_spice_ctrl_error; + } + _g_free0 (itemstr); + itemstr_collection = (_vala_array_free (itemstr_collection, itemstr_collection_length1, (GDestroyNotify) g_free), NULL); + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + _tmp10_ = item; + _tmp11_ = _tmp10_->parent_id; + _tmp12_ = spice_ctrl_menu_find_id (self, _tmp11_); + parent = _tmp12_; + _tmp13_ = parent; + if (_tmp13_ == NULL) { + GError* _tmp14_ = NULL; + _tmp14_ = g_error_new_literal (SPICE_CTRL_ERROR, SPICE_CTRL_ERROR_VALUE, "Invalid parent menu id"); + _inner_error_ = _tmp14_; + _g_object_unref0 (parent); + _g_object_unref0 (item); + if (_inner_error_->domain == SPICE_CTRL_ERROR) { + goto __catch0_spice_ctrl_error; + } + _g_object_unref0 (parent); + _g_object_unref0 (item); + _g_free0 (itemstr); + itemstr_collection = (_vala_array_free (itemstr_collection, itemstr_collection_length1, (GDestroyNotify) g_free), NULL); + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + _tmp15_ = parent; + _tmp16_ = item; + _tmp17_ = _g_object_ref0 (_tmp16_); + _tmp15_->items = g_list_append (_tmp15_->items, _tmp17_); + _g_object_unref0 (parent); + _g_object_unref0 (item); + } + goto __finally0; + __catch0_spice_ctrl_error: + { + GError* e = NULL; + GError* _tmp18_ = NULL; + const gchar* _tmp19_ = NULL; + e = _inner_error_; + _inner_error_ = NULL; + _tmp18_ = e; + _tmp19_ = _tmp18_->message; + g_warning ("menu.vala:95: %s", _tmp19_); + _g_error_free0 (e); + } + __finally0: + if (G_UNLIKELY (_inner_error_ != NULL)) { + _g_free0 (itemstr); + itemstr_collection = (_vala_array_free (itemstr_collection, itemstr_collection_length1, (GDestroyNotify) g_free), NULL); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return NULL; + } + _g_free0 (itemstr); + } + } + itemstr_collection = (_vala_array_free (itemstr_collection, itemstr_collection_length1, (GDestroyNotify) g_free), NULL); + } + return self; +} + + +SpiceCtrlMenu* spice_ctrl_menu_new_from_string (const gchar* str) { + return spice_ctrl_menu_construct_from_string (SPICE_CTRL_TYPE_MENU, str); +} + + +gchar* spice_ctrl_menu_to_string (SpiceCtrlMenu* self) { + gchar* result = NULL; + gchar* str = NULL; + gchar* _tmp0_ = NULL; + GList* _tmp1_ = NULL; + g_return_val_if_fail (self != NULL, NULL); + _tmp0_ = g_strdup (""); + str = _tmp0_; + _tmp1_ = self->items; + { + GList* i_collection = NULL; + GList* i_it = NULL; + i_collection = _tmp1_; + for (i_it = i_collection; i_it != NULL; i_it = i_it->next) { + SpiceCtrlMenuItem* _tmp2_ = NULL; + SpiceCtrlMenuItem* i = NULL; + _tmp2_ = _g_object_ref0 ((SpiceCtrlMenuItem*) i_it->data); + i = _tmp2_; + { + const gchar* _tmp3_ = NULL; + SpiceCtrlMenuItem* _tmp4_ = NULL; + gchar* _tmp5_ = NULL; + gchar* _tmp6_ = NULL; + gchar* _tmp7_ = NULL; + gchar* _tmp8_ = NULL; + gchar* _tmp9_ = NULL; + _tmp3_ = str; + _tmp4_ = i; + _tmp5_ = spice_ctrl_menu_item_to_string (_tmp4_); + _tmp6_ = _tmp5_; + _tmp7_ = g_strconcat ("\n", _tmp6_, NULL); + _tmp8_ = _tmp7_; + _tmp9_ = g_strconcat (_tmp3_, _tmp8_, NULL); + _g_free0 (str); + str = _tmp9_; + _g_free0 (_tmp8_); + _g_free0 (_tmp6_); + _g_object_unref0 (i); + } + } + } + result = str; + return result; +} + + +SpiceCtrlMenu* spice_ctrl_menu_construct (GType object_type) { + SpiceCtrlMenu * self = NULL; + self = (SpiceCtrlMenu*) g_object_new (object_type, NULL); + return self; +} + + +SpiceCtrlMenu* spice_ctrl_menu_new (void) { + return spice_ctrl_menu_construct (SPICE_CTRL_TYPE_MENU); +} + + +static void spice_ctrl_menu_class_init (SpiceCtrlMenuClass * klass) { + spice_ctrl_menu_parent_class = g_type_class_peek_parent (klass); + G_OBJECT_CLASS (klass)->finalize = spice_ctrl_menu_finalize; +} + + +static void spice_ctrl_menu_instance_init (SpiceCtrlMenu * self) { +} + + +static void spice_ctrl_menu_finalize (GObject* obj) { + SpiceCtrlMenu * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, SPICE_CTRL_TYPE_MENU, SpiceCtrlMenu); + __g_list_free__g_object_unref0_0 (self->items); + G_OBJECT_CLASS (spice_ctrl_menu_parent_class)->finalize (obj); +} + + +GType spice_ctrl_menu_get_type (void) { + static volatile gsize spice_ctrl_menu_type_id__volatile = 0; + if (g_once_init_enter (&spice_ctrl_menu_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (SpiceCtrlMenuClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) spice_ctrl_menu_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SpiceCtrlMenu), 0, (GInstanceInitFunc) spice_ctrl_menu_instance_init, NULL }; + GType spice_ctrl_menu_type_id; + spice_ctrl_menu_type_id = g_type_register_static (G_TYPE_OBJECT, "SpiceCtrlMenu", &g_define_type_info, 0); + g_once_init_leave (&spice_ctrl_menu_type_id__volatile, spice_ctrl_menu_type_id); + } + return spice_ctrl_menu_type_id__volatile; +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + +static gint _vala_array_length (gpointer array) { + int length; + length = 0; + if (array) { + while (((gpointer*) array)[length]) { + length++; + } + } + return length; +} + + + diff --git a/src/controller/menu.vala b/src/controller/menu.vala new file mode 100644 index 0000000..7e8fc16 --- /dev/null +++ b/src/controller/menu.vala @@ -0,0 +1,108 @@ +// Copyright (C) 2011 Red Hat, Inc. + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . + +using GLib; +using Custom; +using SpiceProtocol.Controller; + +namespace SpiceCtrl { + +public class MenuItem: Object { + + public Menu submenu; + public int parent_id; + public int id; + public string text; + public string accel; + public SpiceProtocol.Controller.MenuFlags flags; + + public MenuItem (int id, string text, SpiceProtocol.Controller.MenuFlags flags) { + this.id = id; + this.text = text; + this.flags = flags; + } + + public MenuItem.from_string (string str) throws SpiceCtrl.Error { + var params = str.split (SpiceProtocol.Controller.MENU_PARAM_DELIMITER); + if (warn_if (params.length != 5)) + throw new SpiceCtrl.Error.VALUE(""); /* Vala: why is it mandatory to give a string? */ + parent_id = int.parse (params[0]); + id = int.parse (params[1]); + var textaccel = params[2].split ("\t"); + text = textaccel[0]; + if (textaccel.length > 1) + accel = textaccel[1]; + flags = (SpiceProtocol.Controller.MenuFlags)int.parse (params[3]); + + submenu = new Menu (); + } + + public string to_string () { + var sub = submenu.to_string (); + var str = @"pid: $parent_id, id: $id, text: \"$text\", flags: $flags"; + foreach (var l in sub.to_string ().split ("\n")) { + if (l == "") + continue; + str += @"\n $l"; + } + return str; + } +} + +public class Menu: Object { + + public List items; + + public Menu? find_id (int id) { + if (id == 0) + return this; + + foreach (var item in items) { + if (item.id == id) + return item.submenu; + + var menu = item.submenu.find_id (id); + if (menu != null) + return menu; + } + + return null; + } + + public Menu.from_string (string str) { + foreach (var itemstr in str.split (SpiceProtocol.Controller.MENU_ITEM_DELIMITER)) { + try { + if (itemstr.length == 0) + continue; + var item = new MenuItem.from_string (itemstr); + var parent = find_id (item.parent_id); + if (parent == null) + throw new SpiceCtrl.Error.VALUE("Invalid parent menu id"); + parent.items.append (item); + } catch (SpiceCtrl.Error e) { + warning (e.message); + } + } + } + + public string to_string () { + var str = ""; + foreach (var i in items) + str += @"\n$i"; + return str; + } +} + +} // SpiceCtrl diff --git a/src/controller/namedpipe.c b/src/controller/namedpipe.c new file mode 100644 index 0000000..5312218 --- /dev/null +++ b/src/controller/namedpipe.c @@ -0,0 +1,270 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" +#include "namedpipe.h" + +#include +#include +#include +#include + +static void spice_named_pipe_initable_iface_init (GInitableIface *iface); +static gboolean spice_named_pipe_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error); + +G_DEFINE_TYPE_WITH_CODE (SpiceNamedPipe, spice_named_pipe, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + spice_named_pipe_initable_iface_init)); + +enum +{ + PROP_0, + PROP_NAME, + PROP_HANDLE, +}; + +struct _SpiceNamedPipePrivate +{ + gchar * name; + GError * construct_error; + guint inited : 1; + HANDLE handle; +}; + +static void +spice_named_pipe_finalize (GObject *object) +{ + SpiceNamedPipe *np = SPICE_NAMED_PIPE (object); + + g_clear_error (&np->priv->construct_error); + + g_free (np->priv->name); + np->priv->name = NULL; + + if (np->priv->handle) + { + CloseHandle (np->priv->handle); + np->priv->handle = NULL; + } + + if (G_OBJECT_CLASS (spice_named_pipe_parent_class)->finalize) + G_OBJECT_CLASS (spice_named_pipe_parent_class)->finalize (object); +} + +#define DEFAULT_PIPE_BUF_SIZE 4096 + +static void +spice_named_pipe_constructed (GObject *object) +{ + SpiceNamedPipe *np = SPICE_NAMED_PIPE (object); + + if (np->priv->handle) + /* TODO: find a way to ensure user provided handle is a named + pipe, in overlapped mode */ + goto end; + + np->priv->handle = CreateNamedPipe (np->priv->name, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + DEFAULT_PIPE_BUF_SIZE, DEFAULT_PIPE_BUF_SIZE, + 0, NULL); + + if (np->priv->handle == INVALID_HANDLE_VALUE) + { + int errsv = GetLastError (); + gchar *emsg = g_win32_error_message (errsv); + + g_set_error (&np->priv->construct_error, + G_IO_ERROR, + g_io_error_from_win32_error (errsv), + "Error CreateNamedPipe(): %s", + emsg); + + g_free (emsg); + return; + } + + /* TODO: we could have a client backlog by creating many pipes, the + maximum number of outstanding connections.. or we could just let + the named_pipe_listener take multiple NamedPipe instances */ +end: + g_assert (np->priv->handle != INVALID_HANDLE_VALUE); + return; +} + +static void +spice_named_pipe_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceNamedPipe *np = SPICE_NAMED_PIPE (object); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, np->priv->name); + break; + case PROP_HANDLE: + g_value_set_pointer (value, np->priv->handle); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +spice_named_pipe_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceNamedPipe *np = SPICE_NAMED_PIPE (object); + + switch (prop_id) + { + case PROP_NAME: + g_free (np->priv->name); + np->priv->name = g_value_dup_string (value); + break; + case PROP_HANDLE: + np->priv->handle = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +spice_named_pipe_class_init (SpiceNamedPipeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SpiceNamedPipePrivate)); + + gobject_class->set_property = spice_named_pipe_set_property; + gobject_class->get_property = spice_named_pipe_get_property; + gobject_class->finalize = spice_named_pipe_finalize; + gobject_class->constructed = spice_named_pipe_constructed; + + g_object_class_install_property (gobject_class, PROP_NAME, + g_param_spec_string ("name", + "Pipe Name", + "The NamedPipe name", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_HANDLE, + g_param_spec_pointer ("handle", + "Pipe handle", + "The pipe handle", + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +spice_named_pipe_init (SpiceNamedPipe *np) +{ + np->priv = G_TYPE_INSTANCE_GET_PRIVATE (np, + SPICE_TYPE_NAMED_PIPE, + SpiceNamedPipePrivate); +} + +static gboolean +spice_named_pipe_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + SpiceNamedPipe *np; + + g_return_val_if_fail (SPICE_IS_NAMED_PIPE (initable), FALSE); + + np = SPICE_NAMED_PIPE (initable); + + if (cancellable != NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cancellable initialization not supported"); + return FALSE; + } + + np->priv->inited = TRUE; + + if (np->priv->construct_error) + { + if (error) + *error = g_error_copy (np->priv->construct_error); + return FALSE; + } + + + return TRUE; +} + +static void +spice_named_pipe_initable_iface_init (GInitableIface *iface) +{ + iface->init = spice_named_pipe_initable_init; +} + +SpiceNamedPipe * +spice_named_pipe_new (const gchar *name, GError **error) +{ + return SPICE_NAMED_PIPE (g_initable_new (SPICE_TYPE_NAMED_PIPE, + NULL, error, + "name", name, + NULL)); +} + +void * +spice_named_pipe_get_handle (SpiceNamedPipe *namedpipe) +{ + g_return_val_if_fail (SPICE_IS_NAMED_PIPE (namedpipe), NULL); + + return namedpipe->priv->handle; +} + +gboolean +spice_named_pipe_close (SpiceNamedPipe *np, + GError **error) +{ + BOOL res; + + g_return_val_if_fail (SPICE_IS_NAMED_PIPE (np), FALSE); + + res = CloseHandle (np->priv->handle); + np->priv->handle = NULL; + if (!res) + { + int errsv = GetLastError (); + gchar *emsg = g_win32_error_message (errsv); + + g_set_error (error, G_IO_ERROR, + g_io_error_from_win32_error (errsv), + "Error closing handle: %s", + emsg); + g_free (emsg); + return FALSE; + } + + return TRUE; +} diff --git a/src/controller/namedpipe.h b/src/controller/namedpipe.h new file mode 100644 index 0000000..e0e873b --- /dev/null +++ b/src/controller/namedpipe.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __NAMED_PIPE_H__ +#define __NAMED_PIPE_H__ + +#include + +G_BEGIN_DECLS + +#define SPICE_TYPE_NAMED_PIPE (spice_named_pipe_get_type ()) +#define SPICE_NAMED_PIPE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + SPICE_TYPE_NAMED_PIPE, SpiceNamedPipe)) +#define SPICE_NAMED_PIPE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + SPICE_TYPE_NAMED_PIPE, SpiceNamedPipeClass)) +#define SPICE_IS_NAMED_PIPE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + SPICE_TYPE_NAMED_PIPE)) +#define SPICE_IS_NAMED_PIPE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ + SPICE_TYPE_NAMED_PIPE)) +#define SPICE_NAMED_PIPE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + SPICE_TYPE_NAMED_PIPE, SpiceNamedPipeClass)) + +typedef struct _SpiceNamedPipe SpiceNamedPipe; +typedef struct _SpiceNamedPipePrivate SpiceNamedPipePrivate; +typedef struct _SpiceNamedPipeClass SpiceNamedPipeClass; + +struct _SpiceNamedPipeClass +{ + GObjectClass parent_class; +}; + +struct _SpiceNamedPipe +{ + GObject parent_instance; + SpiceNamedPipePrivate *priv; +}; + +GType spice_named_pipe_get_type (void) G_GNUC_CONST; + +SpiceNamedPipe * spice_named_pipe_new (const gchar *name, GError **error); +void * spice_named_pipe_get_handle(SpiceNamedPipe *namedpipe); +gboolean spice_named_pipe_close (SpiceNamedPipe *namedpipe, + GError **error); +G_END_DECLS + +#endif /* __NAMED_PIPE_H__ */ diff --git a/src/controller/namedpipeconnection.c b/src/controller/namedpipeconnection.c new file mode 100644 index 0000000..3173b61 --- /dev/null +++ b/src/controller/namedpipeconnection.c @@ -0,0 +1,245 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" +#include "namedpipeconnection.h" + +#include +#include +#include +#include + +#include +#include + +G_DEFINE_TYPE (SpiceNamedPipeConnection, spice_named_pipe_connection, + G_TYPE_IO_STREAM) + +enum +{ + PROP_0, + PROP_NAMED_PIPE, +}; + +struct _SpiceNamedPipeConnectionPrivate +{ + GInputStream *input_stream; + GOutputStream *output_stream; + SpiceNamedPipe *namedpipe; + gboolean in_dispose; +}; + +static void +spice_named_pipe_connection_init (SpiceNamedPipeConnection *connection) +{ + connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection, + SPICE_TYPE_NAMED_PIPE_CONNECTION, + SpiceNamedPipeConnectionPrivate); +} + +static void +spice_named_pipe_connection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (object); + + switch (prop_id) + { + case PROP_NAMED_PIPE: + g_return_if_fail (c->priv->namedpipe == NULL); + g_value_set_object (value, c->priv->namedpipe); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +spice_named_pipe_connection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (object); + + switch (prop_id) + { + case PROP_NAMED_PIPE: + c->priv->namedpipe = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static GInputStream * +spice_named_pipe_connection_get_input_stream (GIOStream *io_stream) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (io_stream); + HANDLE h = spice_named_pipe_get_handle (c->priv->namedpipe); + + g_return_val_if_fail (h != NULL, NULL); + + if (c->priv->input_stream == NULL) + c->priv->input_stream = g_win32_input_stream_new (h, FALSE); + + return c->priv->input_stream; +} + +static GOutputStream * +spice_named_pipe_connection_get_output_stream (GIOStream *io_stream) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (io_stream); + HANDLE h = spice_named_pipe_get_handle (c->priv->namedpipe); + + g_return_val_if_fail (h != NULL, NULL); + + if (c->priv->output_stream == NULL) + c->priv->output_stream = g_win32_output_stream_new (h, FALSE); + + return c->priv->output_stream; +} + +static void +spice_named_pipe_connection_dispose (GObject *object) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (object); + + c->priv->in_dispose = TRUE; + + if (G_OBJECT_CLASS (spice_named_pipe_connection_parent_class)->dispose) + G_OBJECT_CLASS (spice_named_pipe_connection_parent_class)->dispose (object); + + c->priv->in_dispose = FALSE; +} + +static void +spice_named_pipe_connection_finalize (GObject *object) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (object); + + if (c->priv->output_stream) + { + g_object_unref (c->priv->output_stream); + c->priv->output_stream = NULL; + } + + if (c->priv->input_stream) + { + g_object_unref (c->priv->input_stream); + c->priv->input_stream = NULL; + } + + g_object_unref (c->priv->namedpipe); + + if (G_OBJECT_CLASS (spice_named_pipe_connection_parent_class)->finalize) + G_OBJECT_CLASS (spice_named_pipe_connection_parent_class)->finalize (object); +} + +static gboolean +spice_named_pipe_connection_close (GIOStream *stream, + GCancellable *cancellable, + GError **error) +{ + SpiceNamedPipeConnection *c = SPICE_NAMED_PIPE_CONNECTION (stream); + + if (c->priv->output_stream) + g_output_stream_close (c->priv->output_stream, cancellable, NULL); + if (c->priv->input_stream) + g_input_stream_close (c->priv->input_stream, cancellable, NULL); + + /* Don't close the underlying socket if this is being called + * as part of dispose(); when destroying the GSocketConnection, + * we only want to close the socket if we're holding the last + * reference on it, and in that case it will close itself when + * we unref namedpipe in finalize(). + */ + if (c->priv->in_dispose) + return TRUE; + + return spice_named_pipe_close (c->priv->namedpipe, error); +} + +static void +spice_named_pipe_connection_close_async (GIOStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + GIOStreamClass *class; + GError *error; + + class = G_IO_STREAM_GET_CLASS (stream); + + /* namedpipe close is not blocking, just do it! */ + error = NULL; + if (class->close_fn && + !class->close_fn (stream, cancellable, &error)) + { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), + callback, user_data, + error); + return; + } + + res = g_simple_async_result_new (G_OBJECT (stream), + callback, + user_data, + spice_named_pipe_connection_close_async); + g_simple_async_result_complete_in_idle (res); + g_object_unref (res); +} + +static gboolean +spice_named_pipe_connection_close_finish (GIOStream *stream, + GAsyncResult *result, + GError **error) +{ + return TRUE; +} + +static void +spice_named_pipe_connection_class_init (SpiceNamedPipeConnectionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SpiceNamedPipeConnectionPrivate)); + + gobject_class->set_property = spice_named_pipe_connection_set_property; + gobject_class->get_property = spice_named_pipe_connection_get_property; + gobject_class->dispose = spice_named_pipe_connection_dispose; + gobject_class->finalize = spice_named_pipe_connection_finalize; + + stream_class->get_input_stream = spice_named_pipe_connection_get_input_stream; + stream_class->get_output_stream = spice_named_pipe_connection_get_output_stream; + stream_class->close_fn = spice_named_pipe_connection_close; + stream_class->close_async = spice_named_pipe_connection_close_async; + stream_class->close_finish = spice_named_pipe_connection_close_finish; + + g_object_class_install_property (gobject_class, PROP_NAMED_PIPE, + g_param_spec_object ("namedpipe", + "NamedPipe", + "The associated NamedPipe", + SPICE_TYPE_NAMED_PIPE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/src/controller/namedpipeconnection.h b/src/controller/namedpipeconnection.h new file mode 100644 index 0000000..86f0be6 --- /dev/null +++ b/src/controller/namedpipeconnection.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __NAMED_PIPE_CONNECTION_H__ +#define __NAMED_PIPE_CONNECTION_H__ + +#include +#include "namedpipe.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_NAMED_PIPE_CONNECTION (spice_named_pipe_connection_get_type ()) +#define SPICE_NAMED_PIPE_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + SPICE_TYPE_NAMED_PIPE_CONNECTION, SpiceNamedPipeConnection)) +#define SPICE_NAMED_PIPE_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + SPICE_TYPE_NAMED_PIPE_CONNECTION, SpiceNamedPipeConnectionClass)) +#define SPICE_IS_NAMED_PIPE_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + SPICE_TYPE_NAMED_PIPE_CONNECTION)) +#define SPICE_IS_NAMED_PIPE_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ + SPICE_TYPE_NAMED_PIPE_CONNECTION)) +#define SPICE_NAMED_PIPE_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + SPICE_TYPE_NAMED_PIPE_CONNECTION, SpiceNamedPipeConnectionClass)) + +typedef struct _SpiceNamedPipeConnection SpiceNamedPipeConnection; +typedef struct _SpiceNamedPipeConnectionPrivate SpiceNamedPipeConnectionPrivate; +typedef struct _SpiceNamedPipeConnectionClass SpiceNamedPipeConnectionClass; + +struct _SpiceNamedPipeConnectionClass +{ + GIOStreamClass parent_class; +}; + +struct _SpiceNamedPipeConnection +{ + GIOStream parent_instance; + SpiceNamedPipeConnectionPrivate *priv; +}; + +GType spice_named_pipe_connection_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __NAMED_PIPE_CONNECTION_H__ */ diff --git a/src/controller/namedpipelistener.c b/src/controller/namedpipelistener.c new file mode 100644 index 0000000..b4b6057 --- /dev/null +++ b/src/controller/namedpipelistener.c @@ -0,0 +1,330 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" +#include "namedpipelistener.h" + +#include +#include +#include +#include + +static GSource *g_win32_handle_source_add (HANDLE handle, + GSourceFunc callback, + gpointer user_data); + +G_DEFINE_TYPE (SpiceNamedPipeListener, spice_named_pipe_listener, G_TYPE_OBJECT); + +struct _SpiceNamedPipeListenerPrivate +{ + GQueue namedpipes; +}; + +static void +spice_named_pipe_listener_dispose (GObject *object) +{ + SpiceNamedPipeListener *listener = SPICE_NAMED_PIPE_LISTENER (object); + SpiceNamedPipe *p; + + while ((p = g_queue_pop_head (&listener->priv->namedpipes)) != NULL) + g_object_unref (p); + + g_return_if_fail (g_queue_get_length (&listener->priv->namedpipes) == 0); + g_queue_clear (&listener->priv->namedpipes); + + if (G_OBJECT_CLASS (spice_named_pipe_listener_parent_class)->dispose) + G_OBJECT_CLASS (spice_named_pipe_listener_parent_class)->dispose (object); +} + +static void +spice_named_pipe_listener_class_init (SpiceNamedPipeListenerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SpiceNamedPipeListenerPrivate)); + + gobject_class->dispose = spice_named_pipe_listener_dispose; +} + +static void +spice_named_pipe_listener_init (SpiceNamedPipeListener *listener) +{ + listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener, + SPICE_TYPE_NAMED_PIPE_LISTENER, + SpiceNamedPipeListenerPrivate); + + g_queue_init (&listener->priv->namedpipes); +} + +void +spice_named_pipe_listener_add_named_pipe (SpiceNamedPipeListener *listener, + SpiceNamedPipe *namedpipe) +{ + g_return_if_fail (SPICE_IS_NAMED_PIPE_LISTENER (listener)); + g_return_if_fail (SPICE_IS_NAMED_PIPE (namedpipe)); + + g_queue_push_head (&listener->priv->namedpipes, g_object_ref (namedpipe)); +} + +typedef struct { + GCancellable *cancellable; + GSource *source; + GSimpleAsyncResult *async_result; + SpiceNamedPipe *np; + OVERLAPPED overlapped; +} ConnectData; + +static void +connect_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + ConnectData *c = user_data; + GError *error = NULL; + + g_source_destroy (c->source); + c->source = NULL; + + g_cancellable_set_error_if_cancelled (cancellable, &error); + g_simple_async_result_set_from_error (c->async_result, error); + g_error_free (error); + + g_simple_async_result_complete (c->async_result); + g_object_unref (c->async_result); +} + +static gboolean +connect_ready (gpointer user_data) +{ + ConnectData *c = user_data; + gulong cbret; + gboolean success; + + /* Now complete the result (assuming it wasn't already completed) */ + g_return_val_if_fail (c->async_result != NULL, FALSE); + + success = GetOverlappedResult (c->np, &c->overlapped, &cbret, FALSE); + if (!success) + { + int errsv = GetLastError (); + gchar *emsg = g_win32_error_message (errsv); + + g_simple_async_result_set_error (c->async_result, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "GetOverlappedResult(): %s %d", + emsg, errsv); + g_free (emsg); + } + + g_simple_async_result_complete (c->async_result); + g_object_unref (c->async_result); /* TODO: that sould free c? */ + + return FALSE; +} + +static void +connect_data_free (gpointer data) +{ + ConnectData *c = data; + + if (c->source) + { + g_source_destroy (c->source); + g_source_unref (c->source); + c->source = NULL; + } + if (c->cancellable) + { + g_signal_handlers_disconnect_by_func (c->cancellable, connect_cancelled, c); + g_object_unref (c->cancellable); + c->cancellable = NULL; + } + + if (c->async_result) /* this is only a weak reference */ + c->async_result = NULL; + + if (c->overlapped.hEvent != NULL) + { + CloseHandle (c->overlapped.hEvent); + c->overlapped.hEvent = NULL; + } + + if (c->np != NULL) + { + g_object_unref (c->np); + c->np = NULL; + } + + g_free (c); +} + +void +spice_named_pipe_listener_accept_async (SpiceNamedPipeListener *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + ConnectData *c; + SpiceNamedPipe *namedpipe; + + g_return_if_fail (SPICE_IS_NAMED_PIPE_LISTENER (listener)); + + namedpipe = SPICE_NAMED_PIPE (g_queue_pop_head (&listener->priv->namedpipes)); + /* do not unref, we keep that ref */ + g_return_if_fail (namedpipe != NULL); + + c = g_new0 (ConnectData, 1); + c->np = namedpipe; /* transfer what used to be the avail_namedpipes ref */ + c->async_result = g_simple_async_result_new (G_OBJECT (listener), callback, user_data, + spice_named_pipe_listener_accept_async); + c->overlapped.hEvent = CreateEvent (NULL, /* default security attribute */ + TRUE, /* manual-reset event */ + TRUE, /* initial state = signaled */ + NULL); /* unnamed event object */ + g_simple_async_result_set_op_res_gpointer (c->async_result, c, connect_data_free); + + if (ConnectNamedPipe (spice_named_pipe_get_handle (namedpipe), &c->overlapped) != 0) + { + /* we shouldn't get there if the listener is in non-blocking */ + g_warn_if_reached (); + } + + switch (GetLastError ()) + { + case ERROR_SUCCESS: + case ERROR_IO_PENDING: + break; + case ERROR_PIPE_CONNECTED: + g_simple_async_result_complete_in_idle (c->async_result); + g_object_unref (c->async_result); + return; + default: + g_simple_async_report_error_in_idle (G_OBJECT (listener), + callback, user_data, + G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "ConnectNamedPipe() failed %ld", GetLastError ()); + g_object_unref (c->async_result); + return; + } + + c->source = g_win32_handle_source_add (c->overlapped.hEvent, + connect_ready, c); + + if (cancellable) + { + c->cancellable = g_object_ref (cancellable); + g_signal_connect (cancellable, "cancelled", + G_CALLBACK (connect_cancelled), c); + } +} + +SpiceNamedPipeConnection * +spice_named_pipe_listener_accept_finish (SpiceNamedPipeListener *listener, + GAsyncResult *result, + GObject **source_object, + GError **error) +{ + GSimpleAsyncResult *simple; + ConnectData *c; + SpiceNamedPipeConnection *connection; + + g_return_val_if_fail (SPICE_IS_NAMED_PIPE_LISTENER (listener), NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (listener), + spice_named_pipe_listener_accept_async), + NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + c = g_simple_async_result_get_op_res_gpointer (simple); + + connection = g_object_new (SPICE_TYPE_NAMED_PIPE_CONNECTION, + "namedpipe", c->np, + NULL); + return connection; +} + +SpiceNamedPipeListener * +spice_named_pipe_listener_new (void) +{ + return g_object_new (SPICE_TYPE_NAMED_PIPE_LISTENER, NULL); +} + +/* Windows HANDLE GSource - from gio/gwin32resolver.c */ + +typedef struct { + GSource source; + GPollFD pollfd; +} GWin32HandleSource; + +static gboolean +g_win32_handle_source_prepare (GSource *source, + gint *timeout) +{ + *timeout = -1; + return FALSE; +} + +static gboolean +g_win32_handle_source_check (GSource *source) +{ + GWin32HandleSource *hsource = (GWin32HandleSource *)source; + + return hsource->pollfd.revents; +} + +static gboolean +g_win32_handle_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + return (*callback) (user_data); +} + +static void +g_win32_handle_source_finalize (GSource *source) +{ + ; +} + +GSourceFuncs g_win32_handle_source_funcs = { + g_win32_handle_source_prepare, + g_win32_handle_source_check, + g_win32_handle_source_dispatch, + g_win32_handle_source_finalize +}; + +static GSource * +g_win32_handle_source_add (HANDLE handle, + GSourceFunc callback, + gpointer user_data) +{ + GWin32HandleSource *hsource; + GSource *source; + + source = g_source_new (&g_win32_handle_source_funcs, sizeof (GWin32HandleSource)); + hsource = (GWin32HandleSource *)source; + hsource->pollfd.fd = (gint)handle; + hsource->pollfd.events = G_IO_IN; + hsource->pollfd.revents = 0; + g_source_add_poll (source, &hsource->pollfd); + + g_source_set_callback (source, callback, user_data, NULL); + g_source_attach (source, g_main_context_get_thread_default ()); + return source; +} diff --git a/src/controller/namedpipelistener.h b/src/controller/namedpipelistener.h new file mode 100644 index 0000000..c2dbd0a --- /dev/null +++ b/src/controller/namedpipelistener.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __NAMED_PIPE_LISTENER_H__ +#define __NAMED_PIPE_LISTENER_H__ + +#include + +#include "namedpipe.h" +#include "namedpipeconnection.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_NAMED_PIPE_LISTENER (spice_named_pipe_listener_get_type ()) +#define SPICE_NAMED_PIPE_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + SPICE_TYPE_NAMED_PIPE_LISTENER, SpiceNamedPipeListener)) +#define SPICE_NAMED_PIPE_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + SPICE_TYPE_NAMED_PIPE_LISTENER, SpiceNamedPipeListenerClass)) +#define SPICE_IS_NAMED_PIPE_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + SPICE_TYPE_NAMED_PIPE_LISTENER)) +#define SPICE_IS_NAMED_PIPE_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ + SPICE_TYPE_NAMED_PIPE_LISTENER)) +#define SPICE_NAMED_PIPE_LISTENER_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + SPICE_TYPE_NAMED_PIPE_LISTENER, SpiceNamedPipeListenerClass)) + +typedef struct _SpiceNamedPipeListener SpiceNamedPipeListener; +typedef struct _SpiceNamedPipeListenerPrivate SpiceNamedPipeListenerPrivate; +typedef struct _SpiceNamedPipeListenerClass SpiceNamedPipeListenerClass; + +struct _SpiceNamedPipeListenerClass +{ + GObjectClass parent_class; +}; + +struct _SpiceNamedPipeListener +{ + GObject parent_instance; + SpiceNamedPipeListenerPrivate *priv; +}; + +GType spice_named_pipe_listener_get_type (void) G_GNUC_CONST; + +SpiceNamedPipeListener * spice_named_pipe_listener_new (void); +void spice_named_pipe_listener_add_named_pipe (SpiceNamedPipeListener *listener, + SpiceNamedPipe *namedpipe); +void spice_named_pipe_listener_accept_async (SpiceNamedPipeListener *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SpiceNamedPipeConnection * spice_named_pipe_listener_accept_finish (SpiceNamedPipeListener *listener, + GAsyncResult *result, + GObject **source_object, + GError **error); + +G_END_DECLS + +#endif /* __NAMED_PIPE_LISTENER_H__ */ diff --git a/src/controller/spice-controller-listener.c b/src/controller/spice-controller-listener.c new file mode 100644 index 0000000..98baf33 --- /dev/null +++ b/src/controller/spice-controller-listener.c @@ -0,0 +1,159 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#include "spice-controller-listener.h" + +#ifdef G_OS_WIN32 +#include +#include "namedpipe.h" +#include "namedpipelistener.h" +#include "win32-util.h" +#endif + +#ifdef G_OS_UNIX +#include +#endif + +/** + * SpiceControllerListenerError: + * @SPICE_CONTROLLER_LISTENER_ERROR_VALUE: invalid value. + * + * Possible errors of controller listener related functions. + **/ + +/** + * SPICE_CONTROLLER_LISTENER_ERROR: + * + * The error domain of the controller listener subsystem. + **/ +GQuark +spice_controller_listener_error_quark (void) +{ + return g_quark_from_static_string ("spice-controller-listener-error"); +} + +GObject* +spice_controller_listener_new (const gchar *address, GError **error) +{ + GObject *listener = NULL; + gchar *addr = NULL; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + addr = g_strdup (address); + +#ifdef G_OS_WIN32 + if (addr == NULL) + addr = g_strdup (g_getenv ("SPICE_XPI_NAMEDPIPE")); + if (addr == NULL) + addr = g_strdup_printf ("\\\\.\\pipe\\SpiceController-%" G_GUINT64_FORMAT, (guint64)GetCurrentProcessId ()); +#else + if (addr == NULL) + addr = g_strdup (g_getenv ("SPICE_XPI_SOCKET")); +#endif + if (addr == NULL) { + g_set_error (error, + SPICE_CONTROLLER_LISTENER_ERROR, + SPICE_CONTROLLER_LISTENER_ERROR_VALUE, +#ifdef G_OS_WIN32 + "Missing namedpipe address" +#else + "Missing socket address" +#endif + ); + goto end; + } + + g_unlink (addr); + +#ifdef G_OS_WIN32 + { + SpiceNamedPipe *np; + + listener = G_OBJECT (spice_named_pipe_listener_new ()); + + np = spice_win32_user_pipe_new (addr, error); + if (!np) { + g_object_unref (listener); + listener = NULL; + goto end; + } + + spice_named_pipe_listener_add_named_pipe (SPICE_NAMED_PIPE_LISTENER (listener), np); + } +#else + { + listener = G_OBJECT (g_socket_listener_new ()); + + if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener), + G_SOCKET_ADDRESS (g_unix_socket_address_new (addr)), + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, + NULL, + error)) + g_warning ("failed to add address"); + } +#endif + +end: + g_free (addr); + return listener; +} + +void +spice_controller_listener_accept_async (GObject *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(G_IS_OBJECT(listener)); + +#ifdef G_OS_WIN32 + spice_named_pipe_listener_accept_async (SPICE_NAMED_PIPE_LISTENER (listener), cancellable, callback, user_data); +#else + g_socket_listener_accept_async (G_SOCKET_LISTENER (listener), cancellable, callback, user_data); +#endif +} + +GIOStream* +spice_controller_listener_accept_finish (GObject *listener, + GAsyncResult *result, + GObject **source_object, + GError **error) +{ + g_return_val_if_fail(G_IS_OBJECT(listener), NULL); + +#ifdef G_OS_WIN32 + SpiceNamedPipeConnection *np; + np = spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error); + if (np) + return G_IO_STREAM (np); +#else + GSocketConnection *socket; + socket = g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error); + if (socket) + return G_IO_STREAM (socket); +#endif + + return NULL; +} diff --git a/src/controller/spice-controller-listener.h b/src/controller/spice-controller-listener.h new file mode 100644 index 0000000..a50bdea --- /dev/null +++ b/src/controller/spice-controller-listener.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CONTROLLER_LISTENER_H__ +#define __SPICE_CONTROLLER_LISTENER_H__ + +#include + +G_BEGIN_DECLS + +#define SPICE_CONTROLLER_LISTENER_ERROR spice_controller_listener_error_quark () +GQuark spice_controller_listener_error_quark (void); + +typedef enum +{ + SPICE_CONTROLLER_LISTENER_ERROR_VALUE /* incorrect value */ +} SpiceControllerListenerError; + + +GObject* spice_controller_listener_new (const gchar *address, GError **error); + +void spice_controller_listener_accept_async (GObject *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +GIOStream* spice_controller_listener_accept_finish (GObject *listener, + GAsyncResult *result, + GObject **source_object, + GError **error); +G_END_DECLS + +#endif /* __SPICE_CONTROLLER_LISTENER_H__ */ diff --git a/src/controller/spice-controller.h b/src/controller/spice-controller.h new file mode 100644 index 0000000..8dacbc7 --- /dev/null +++ b/src/controller/spice-controller.h @@ -0,0 +1,172 @@ +/* spice-controller.h generated by valac 0.32.0, the Vala compiler, do not modify */ + + +#ifndef __SPICE_CONTROLLER_H__ +#define __SPICE_CONTROLLER_H__ + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + + +#define SPICE_CTRL_TYPE_MENU_ITEM (spice_ctrl_menu_item_get_type ()) +#define SPICE_CTRL_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItem)) +#define SPICE_CTRL_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) +#define SPICE_CTRL_IS_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU_ITEM)) +#define SPICE_CTRL_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU_ITEM, SpiceCtrlMenuItemClass)) + +typedef struct _SpiceCtrlMenuItem SpiceCtrlMenuItem; +typedef struct _SpiceCtrlMenuItemClass SpiceCtrlMenuItemClass; +typedef struct _SpiceCtrlMenuItemPrivate SpiceCtrlMenuItemPrivate; + +#define SPICE_CTRL_TYPE_MENU (spice_ctrl_menu_get_type ()) +#define SPICE_CTRL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenu)) +#define SPICE_CTRL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) +#define SPICE_CTRL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_MENU)) +#define SPICE_CTRL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_MENU, SpiceCtrlMenuClass)) + +typedef struct _SpiceCtrlMenu SpiceCtrlMenu; +typedef struct _SpiceCtrlMenuClass SpiceCtrlMenuClass; +typedef struct _SpiceCtrlMenuPrivate SpiceCtrlMenuPrivate; + +#define SPICE_CTRL_TYPE_CONTROLLER (spice_ctrl_controller_get_type ()) +#define SPICE_CTRL_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlController)) +#define SPICE_CTRL_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlControllerClass)) +#define SPICE_CTRL_IS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_CONTROLLER)) +#define SPICE_CTRL_IS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_CONTROLLER)) +#define SPICE_CTRL_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_CONTROLLER, SpiceCtrlControllerClass)) + +typedef struct _SpiceCtrlController SpiceCtrlController; +typedef struct _SpiceCtrlControllerClass SpiceCtrlControllerClass; +typedef struct _SpiceCtrlControllerPrivate SpiceCtrlControllerPrivate; + +#define SPICE_CTRL_TYPE_FOREIGN_MENU (spice_ctrl_foreign_menu_get_type ()) +#define SPICE_CTRL_FOREIGN_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenu)) +#define SPICE_CTRL_FOREIGN_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenuClass)) +#define SPICE_CTRL_IS_FOREIGN_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU)) +#define SPICE_CTRL_IS_FOREIGN_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_CTRL_TYPE_FOREIGN_MENU)) +#define SPICE_CTRL_FOREIGN_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_CTRL_TYPE_FOREIGN_MENU, SpiceCtrlForeignMenuClass)) + +typedef struct _SpiceCtrlForeignMenu SpiceCtrlForeignMenu; +typedef struct _SpiceCtrlForeignMenuClass SpiceCtrlForeignMenuClass; +typedef struct _SpiceCtrlForeignMenuPrivate SpiceCtrlForeignMenuPrivate; + +struct _SpiceCtrlMenuItem { + GObject parent_instance; + SpiceCtrlMenuItemPrivate * priv; + SpiceCtrlMenu* submenu; + gint parent_id; + gint id; + gchar* text; + gchar* accel; + unsigned int flags; +}; + +struct _SpiceCtrlMenuItemClass { + GObjectClass parent_class; +}; + +typedef enum { + SPICE_CTRL_ERROR_VALUE +} SpiceCtrlError; +#define SPICE_CTRL_ERROR spice_ctrl_error_quark () +struct _SpiceCtrlMenu { + GObject parent_instance; + SpiceCtrlMenuPrivate * priv; + GList* items; +}; + +struct _SpiceCtrlMenuClass { + GObjectClass parent_class; +}; + +struct _SpiceCtrlController { + GObject parent_instance; + SpiceCtrlControllerPrivate * priv; +}; + +struct _SpiceCtrlControllerClass { + GObjectClass parent_class; +}; + +struct _SpiceCtrlForeignMenu { + GObject parent_instance; + SpiceCtrlForeignMenuPrivate * priv; +}; + +struct _SpiceCtrlForeignMenuClass { + GObjectClass parent_class; +}; + + +GType spice_ctrl_menu_item_get_type (void) G_GNUC_CONST; +GType spice_ctrl_menu_get_type (void) G_GNUC_CONST; +SpiceCtrlMenuItem* spice_ctrl_menu_item_new (gint id, const gchar* text, unsigned int flags); +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct (GType object_type, gint id, const gchar* text, unsigned int flags); +GQuark spice_ctrl_error_quark (void); +SpiceCtrlMenuItem* spice_ctrl_menu_item_new_from_string (const gchar* str, GError** error); +SpiceCtrlMenuItem* spice_ctrl_menu_item_construct_from_string (GType object_type, const gchar* str, GError** error); +gchar* spice_ctrl_menu_item_to_string (SpiceCtrlMenuItem* self); +SpiceCtrlMenu* spice_ctrl_menu_find_id (SpiceCtrlMenu* self, gint id); +SpiceCtrlMenu* spice_ctrl_menu_new_from_string (const gchar* str); +SpiceCtrlMenu* spice_ctrl_menu_construct_from_string (GType object_type, const gchar* str); +gchar* spice_ctrl_menu_to_string (SpiceCtrlMenu* self); +SpiceCtrlMenu* spice_ctrl_menu_new (void); +SpiceCtrlMenu* spice_ctrl_menu_construct (GType object_type); +GType spice_ctrl_controller_get_type (void) G_GNUC_CONST; +void spice_ctrl_controller_menu_item_click_msg (SpiceCtrlController* self, gint32 item_id); +void spice_ctrl_controller_send_msg (SpiceCtrlController* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +gboolean spice_ctrl_controller_send_msg_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error); +SpiceCtrlController* spice_ctrl_controller_new (void); +SpiceCtrlController* spice_ctrl_controller_construct (GType object_type); +void spice_ctrl_controller_listen (SpiceCtrlController* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_controller_listen_finish (SpiceCtrlController* self, GAsyncResult* _res_, GError** error); +const gchar* spice_ctrl_controller_get_host (SpiceCtrlController* self); +guint32 spice_ctrl_controller_get_port (SpiceCtrlController* self); +guint32 spice_ctrl_controller_get_sport (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_password (SpiceCtrlController* self); +unsigned int spice_ctrl_controller_get_display_flags (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_tls_ciphers (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_host_subject (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_ca_file (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_title (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_hotkeys (SpiceCtrlController* self); +gchar** spice_ctrl_controller_get_secure_channels (SpiceCtrlController* self, int* result_length1); +gchar** spice_ctrl_controller_get_disable_channels (SpiceCtrlController* self, int* result_length1); +SpiceCtrlMenu* spice_ctrl_controller_get_menu (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_smartcard (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_send_cad (SpiceCtrlController* self); +gchar** spice_ctrl_controller_get_disable_effects (SpiceCtrlController* self, int* result_length1); +guint32 spice_ctrl_controller_get_color_depth (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_usbredir (SpiceCtrlController* self); +gboolean spice_ctrl_controller_get_enable_usb_autoshare (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_usb_filter (SpiceCtrlController* self); +const gchar* spice_ctrl_controller_get_proxy (SpiceCtrlController* self); +GType spice_ctrl_foreign_menu_get_type (void) G_GNUC_CONST; +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_new (void); +SpiceCtrlForeignMenu* spice_ctrl_foreign_menu_construct (GType object_type); +void spice_ctrl_foreign_menu_menu_item_click_msg (SpiceCtrlForeignMenu* self, gint32 item_id); +void spice_ctrl_foreign_menu_menu_item_checked_msg (SpiceCtrlForeignMenu* self, gint32 item_id, gboolean checked); +void spice_ctrl_foreign_menu_app_activated_msg (SpiceCtrlForeignMenu* self, gboolean activated); +void spice_ctrl_foreign_menu_send_msg (SpiceCtrlForeignMenu* self, guint8* p, int p_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +gboolean spice_ctrl_foreign_menu_send_msg_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error); +void spice_ctrl_foreign_menu_listen (SpiceCtrlForeignMenu* self, const gchar* addr, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_foreign_menu_listen_finish (SpiceCtrlForeignMenu* self, GAsyncResult* _res_, GError** error); +SpiceCtrlMenu* spice_ctrl_foreign_menu_get_menu (SpiceCtrlForeignMenu* self); +const gchar* spice_ctrl_foreign_menu_get_title (SpiceCtrlForeignMenu* self); +void spice_ctrl_input_stream_read (GInputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_input_stream_read_finish (GAsyncResult* _res_, GError** error); +void spice_ctrl_output_stream_write (GOutputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_output_stream_write_finish (GAsyncResult* _res_, GError** error); + + +G_END_DECLS + +#endif diff --git a/src/controller/spice-foreign-menu-listener.c b/src/controller/spice-foreign-menu-listener.c new file mode 100644 index 0000000..5e62606 --- /dev/null +++ b/src/controller/spice-foreign-menu-listener.c @@ -0,0 +1,161 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#include "spice-foreign-menu-listener.h" + +#ifdef G_OS_WIN32 +#include +#include "namedpipe.h" +#include "namedpipelistener.h" +#include "win32-util.h" +#endif + +#ifdef G_OS_UNIX +#include +#endif + +/** + * SpiceForeignMenuListenerError: + * @SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE: invalid value. + * + * Possible errors of foreign menu listener related functions. + **/ + +/** + * SPICE_FOREIGN_MENU_LISTENER_ERROR: + * + * The error domain of the foreign menu listener subsystem. + **/ +GQuark +spice_foreign_menu_listener_error_quark (void) +{ + return g_quark_from_static_string ("spice-foreign-menu-listener-error"); +} + +GObject* +spice_foreign_menu_listener_new (const gchar *address, GError **error) +{ + GObject *listener = NULL; + gchar *addr = NULL; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + addr = g_strdup (address); + +#ifdef G_OS_WIN32 + if (addr == NULL) + addr = g_strdup (g_getenv ("SPICE_FOREIGN_MENU_NAMEDPIPE")); + if (addr == NULL) + addr = g_strdup_printf ("\\\\.\\pipe\\SpiceForeignMenu-%" G_GUINT64_FORMAT, (guint64)GetCurrentProcessId ()); +#else + if (addr == NULL) + addr = g_strdup (g_getenv ("SPICE_FOREIGN_MENU_SOCKET")); + if (addr == NULL) + addr = g_strdup_printf ("/tmp/SpiceForeignMenu-%" G_GUINT64_FORMAT ".uds", (guint64)getpid ()); +#endif + if (addr == NULL) { + g_set_error (error, + SPICE_FOREIGN_MENU_LISTENER_ERROR, + SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE, +#ifdef G_OS_WIN32 + "Missing namedpipe address" +#else + "Missing socket address" +#endif + ); + goto end; + } + + g_unlink (addr); + +#ifdef G_OS_WIN32 + { + SpiceNamedPipe *np; + + listener = G_OBJECT (spice_named_pipe_listener_new ()); + + np = spice_win32_user_pipe_new (addr, error); + if (!np) { + g_object_unref (listener); + listener = NULL; + goto end; + } + + spice_named_pipe_listener_add_named_pipe (SPICE_NAMED_PIPE_LISTENER (listener), np); + } +#else + { + listener = G_OBJECT (g_socket_listener_new ()); + + if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener), + G_SOCKET_ADDRESS (g_unix_socket_address_new (addr)), + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, + NULL, + error)) + g_warning ("failed to add address"); + } +#endif + +end: + g_free (addr); + return listener; +} + +void +spice_foreign_menu_listener_accept_async (GObject *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(G_IS_OBJECT(listener)); + +#ifdef G_OS_WIN32 + spice_named_pipe_listener_accept_async (SPICE_NAMED_PIPE_LISTENER (listener), cancellable, callback, user_data); +#else + g_socket_listener_accept_async (G_SOCKET_LISTENER (listener), cancellable, callback, user_data); +#endif +} + +GIOStream* +spice_foreign_menu_listener_accept_finish (GObject *listener, + GAsyncResult *result, + GObject **source_object, + GError **error) +{ + g_return_val_if_fail(G_IS_OBJECT(listener), NULL); + +#ifdef G_OS_WIN32 + SpiceNamedPipeConnection *np; + np = spice_named_pipe_listener_accept_finish (SPICE_NAMED_PIPE_LISTENER (listener), result, source_object, error); + if (np) + return G_IO_STREAM (np); +#else + GSocketConnection *socket; + socket = g_socket_listener_accept_finish (G_SOCKET_LISTENER (listener), result, source_object, error); + if (socket) + return G_IO_STREAM (socket); +#endif + + return NULL; +} diff --git a/src/controller/spice-foreign-menu-listener.h b/src/controller/spice-foreign-menu-listener.h new file mode 100644 index 0000000..1071528 --- /dev/null +++ b/src/controller/spice-foreign-menu-listener.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_FOREIGN_MENU_LISTENER_H__ +#define __SPICE_FOREIGN_MENU_LISTENER_H__ + +#include + +G_BEGIN_DECLS + +#define SPICE_FOREIGN_MENU_LISTENER_ERROR spice_foreign_menu_listener_error_quark () +GQuark spice_foreign_menu_listener_error_quark (void); + +typedef enum +{ + SPICE_FOREIGN_MENU_LISTENER_ERROR_VALUE /* incorrect value */ +} SpiceForeignMenuListenerError; + + +GObject* spice_foreign_menu_listener_new (const gchar *address, GError **error); + +void spice_foreign_menu_listener_accept_async (GObject *listener, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +GIOStream* spice_foreign_menu_listener_accept_finish (GObject *listener, + GAsyncResult *result, + GObject **source_object, + GError **error); +G_END_DECLS + +#endif /* __SPICE_FOREIGN_MENU_LISTENER_H__ */ diff --git a/src/controller/test.c b/src/controller/test.c new file mode 100644 index 0000000..783499c --- /dev/null +++ b/src/controller/test.c @@ -0,0 +1,289 @@ +/* Copyright (C) 2011 Red Hat, Inc. */ + +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2.1 of the License, or (at your option) any later version. */ + +/* This library is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* Lesser General Public License for more details. */ + +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; if not, see . */ + +#include "config.h" + +#include +#include +#include + +#include "spice-controller.h" + +#ifdef WIN32 +#include +#define PIPE_NAME TEXT("\\\\.\\pipe\\SpiceController-%lu") +static HANDLE pipe = INVALID_HANDLE_VALUE; +#else + +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include + +#define PIPE_NAME "/tmp/test" +static int sock = -1; + +#endif + +#define PIPE_NAME_MAX_LEN 256 + +void write_to_pipe (const void* data, size_t len) +{ +#ifdef WIN32 + DWORD written; + if (!WriteFile (pipe, data, len, &written, NULL) || written != len) { + printf("Write to pipe failed %lu\n", GetLastError()); + } +#else + if (send (sock, data, len, 0) != len) { + printf ("send failed, (%d) %s\n", errno, strerror(errno)); + } +#endif +} + +gboolean send_init (void) +{ + ControllerInit msg = { + { CONTROLLER_MAGIC, CONTROLLER_VERSION, sizeof (msg) }, + 0, + CONTROLLER_FLAG_EXCLUSIVE + }; + + write_to_pipe(&msg, sizeof (msg)); + return FALSE; +} + +void send_msg (uint32_t id) +{ + ControllerMsg msg = { + id, sizeof (msg) + }; + + write_to_pipe (&msg, sizeof (msg)); +} + +void send_value (uint32_t id, uint32_t value) +{ + ControllerValue msg = { + { id, sizeof(msg) }, + value + }; + + write_to_pipe (&msg, sizeof (msg)); +} + +void send_data (uint32_t id, uint8_t* data, size_t data_size) +{ + size_t size = sizeof (ControllerData) + data_size; + ControllerData* msg = (ControllerData*)g_malloc0 (size); + + msg->base.id = id; + msg->base.size = (uint32_t)size; + memcpy (msg->data, data, data_size); + write_to_pipe (msg, size); + g_free (msg); +} + +ssize_t read_from_pipe (void* data, size_t size) +{ + ssize_t read; +#ifdef WIN32 + DWORD bytes; + if (!ReadFile (pipe, data, size, &bytes, NULL)) { + printf ("Read from pipe failed %lu\n", GetLastError()); + } + read = bytes; +#else + read = recv (sock, data, size, 0); + if ((read == -1 || read == 0)) { + printf ("recv failed, (%d) %s\n", errno, strerror (errno)); + } +#endif + return read; +} + +#define HOST "localhost" +#define PORT 5931 +#define SPORT 0 +#define PWD "P@s5w0rd" +#define SECURE_CHANNELS "main,inputs,playback" +#define DISABLED_CHANNELS "playback,record" +#define TITLE "Hello from controller" +#define HOTKEYS "toggle-fullscreen=shift+f1,release-cursor=shift+f2" +#define MENU "0\r4864\rS&end Ctrl+Alt+Del\tCtrl+Alt+End\r0\r\n" \ + "0\r5120\r&Toggle full screen\tShift+F11\r0\r\n" \ + "0\r1\r&Special keys\r4\r\n" \ + "1\r5376\r&Send Shift+F11\r0\r\n" \ + "1\r5632\r&Send Shift+F12\r0\r\n" \ + "1\r5888\r&Send Ctrl+Alt+End\r0\r\n" \ + "0\r1\r-\r1\r\n" \ + "0\r2\rChange CD\r4\r\n" \ + "2\r3\rNo CDs\r0\r\n" \ + "2\r4\r[Eject]\r0\r\n" \ + "0\r5\r-\r1\r\n" \ + "0\r6\rPlay\r0\r\n" \ + "0\r7\rSuspend\r0\r\n" \ + "0\r8\rStop\r0\r\n" + +#define TLS_CIPHERS "TLS_C1PHERS" +#define CA_FILE "C@_FILE" +#define HOST_SUBJECT "Host_SUBJ3CT" + +SpiceCtrlController *ctrl; +GMainLoop *loop; + +void signaled (GObject *gobject, const gchar *signal_name) +{ + g_message ("signaled: %s", signal_name); + if (g_str_equal (signal_name, "hide")) { + spice_ctrl_controller_menu_item_click_msg (ctrl, 42); + g_timeout_add (1000, (GSourceFunc)g_main_loop_quit, loop); + } +} + +void notified (GObject *gobject, GParamSpec *pspec, + gpointer user_data) +{ + GValue value = { 0, }; + GValue strvalue = { 0, }; + + g_return_if_fail (gobject != NULL); + g_return_if_fail (pspec != NULL); + + g_value_init (&value, pspec->value_type); + g_value_init (&strvalue, G_TYPE_STRING); + g_object_get_property (gobject, pspec->name, &value); + + if (pspec->value_type == G_TYPE_STRV) { + gchar** p = (gchar **)g_value_get_boxed (&value); + g_message ("notify::%s == ", pspec->name); + while (*p) + g_message ("%s", *p++); + } else if (G_TYPE_IS_OBJECT(pspec->value_type)) { + GObject *o = g_value_get_object (&value); + g_message ("notify::%s == %s", pspec->name, o ? G_OBJECT_TYPE_NAME (o) : "null"); + } else { + g_value_transform (&value, &strvalue); + g_message ("notify::%s = %s", pspec->name, g_value_get_string (&strvalue)); + } + + g_value_unset (&value); + g_value_unset (&strvalue); +} + +void connect_signals (gpointer obj) +{ + guint i, n_ids = 0; + guint *ids = NULL; + GType type = G_OBJECT_TYPE (obj); + + ids = g_signal_list_ids (type, &n_ids); + for (i = 0; i < n_ids; i++) { + const gchar *name = g_signal_name (ids[i]); + g_signal_connect (obj, name, G_CALLBACK (signaled), (gpointer)name); + } +} + +int main (int argc, char *argv[]) +{ +#ifdef WIN32 + int spicec_pid = (argc > 1 ? atoi (argv[1]) : 0); +#endif + char* host = (argc > 2 ? argv[2] : (char*)HOST); + int port = (argc > 3 ? atoi (argv[3]) : PORT); + char pipe_name[PIPE_NAME_MAX_LEN]; + ControllerValue msg; + ssize_t read; + + ctrl = spice_ctrl_controller_new (); + loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (ctrl, "notify", G_CALLBACK (notified), NULL); + connect_signals (ctrl); + +#ifdef WIN32 + snprintf (pipe_name, PIPE_NAME_MAX_LEN, PIPE_NAME, spicec_pid); + spice_ctrl_controller_listen (ctrl, pipe_name, NULL, NULL); + + printf ("Creating Spice controller connection %s\n", pipe_name); + pipe = CreateFile (pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (pipe == INVALID_HANDLE_VALUE) { + printf ("Could not open pipe %lu\n", GetLastError()); + return -1; + } +#else + spice_ctrl_controller_listen (ctrl, PIPE_NAME, NULL, NULL); + + snprintf (pipe_name, PIPE_NAME_MAX_LEN, PIPE_NAME); + printf ("Creating a controller connection %s\n", pipe_name); + struct sockaddr_un remote; + if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { + printf ("Could not open socket, (%d) %s\n", errno, strerror(errno)); + return -1; + } + remote.sun_family = AF_UNIX; + strcpy (remote.sun_path, pipe_name); + if (connect (sock, (struct sockaddr *)&remote, + strlen (remote.sun_path) + sizeof(remote.sun_family)) == -1) { + printf ("Socket connect failed, (%d) %s\n", errno, strerror(errno)); + close (sock); + return -1; + } +#endif + + /* TODO: we rely on socket / pipe buffer... which is lame :) */ + send_init (); + + send_data (CONTROLLER_HOST, (uint8_t*)host, strlen(host) + 1); + send_value (CONTROLLER_PORT, port); + send_value (CONTROLLER_SPORT, SPORT); + send_data (CONTROLLER_PASSWORD, (uint8_t*)PWD, strlen(PWD) + 1); + send_data (CONTROLLER_SECURE_CHANNELS, (uint8_t*)SECURE_CHANNELS, strlen(SECURE_CHANNELS) + 1); + send_data (CONTROLLER_DISABLE_CHANNELS, (uint8_t*)DISABLED_CHANNELS, strlen(DISABLED_CHANNELS) + 1); + send_data (CONTROLLER_TLS_CIPHERS, (uint8_t*)TLS_CIPHERS, strlen(TLS_CIPHERS) + 1); + send_data (CONTROLLER_CA_FILE, (uint8_t*)CA_FILE, strlen(CA_FILE) + 1); + send_data (CONTROLLER_HOST_SUBJECT, (uint8_t*)HOST_SUBJECT, strlen(HOST_SUBJECT) + 1); + send_data (CONTROLLER_SET_TITLE, (uint8_t*)TITLE, strlen(TITLE) + 1); + send_data (CONTROLLER_HOTKEYS, (uint8_t*)HOTKEYS, strlen(HOTKEYS) + 1); + send_data (CONTROLLER_CREATE_MENU, (uint8_t*)MENU, strlen(MENU)); + + send_value (CONTROLLER_FULL_SCREEN, /*CONTROLLER_SET_FULL_SCREEN |*/ CONTROLLER_AUTO_DISPLAY_RES); + + send_msg (CONTROLLER_SHOW); + send_msg (CONTROLLER_CONNECT); + send_msg (CONTROLLER_SHOW); + send_msg (CONTROLLER_DELETE_MENU); + send_msg (CONTROLLER_HIDE); + + g_main_loop_run (loop); + + while ((read = read_from_pipe (&msg, sizeof(msg))) == sizeof(msg)) { + printf ("Received id %u, size %u, value %u\n", msg.base.id, msg.base.size, msg.value); + if (msg.value == 42) + break; + } + +#ifdef WIN32 + CloseHandle (pipe); +#else + close (sock); +#endif + g_object_unref (ctrl); + return 0; +} diff --git a/src/controller/util.c b/src/controller/util.c new file mode 100644 index 0000000..44eb8be --- /dev/null +++ b/src/controller/util.c @@ -0,0 +1,388 @@ +/* util.c generated by valac 0.32.0, the Vala compiler + * generated from util.vala, do not modify */ + +/* Copyright (C) 2012 Red Hat, Inc.*/ +/* This library is free software; you can redistribute it and/or*/ +/* modify it under the terms of the GNU Lesser General Public*/ +/* License as published by the Free Software Foundation; either*/ +/* version 2.1 of the License, or (at your option) any later version.*/ +/* This library is distributed in the hope that it will be useful,*/ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of*/ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU*/ +/* Lesser General Public License for more details.*/ +/* You should have received a copy of the GNU Lesser General Public*/ +/* License along with this library; if not, see .*/ + +#include +#include +#include + +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +typedef struct _SpiceCtrlInputStreamReadData SpiceCtrlInputStreamReadData; +typedef struct _SpiceCtrlOutputStreamWriteData SpiceCtrlOutputStreamWriteData; + +struct _SpiceCtrlInputStreamReadData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + GInputStream* stream; + guint8* buffer; + gint buffer_length1; + gint length; + guint8* _tmp0_; + gint _tmp0__length1; + gssize i; + gssize _tmp1_; + gint _tmp2_; + gssize n; + GInputStream* _tmp3_; + guint8* _tmp4_; + gint _tmp4__length1; + gssize _tmp5_; + gint _tmp6_; + gssize _tmp7_; + gssize _tmp8_; + GError* _tmp9_; + gssize _tmp10_; + gssize _tmp11_; + GError * _inner_error_; +}; + +struct _SpiceCtrlOutputStreamWriteData { + int _state_; + GObject* _source_object_; + GAsyncResult* _res_; + GSimpleAsyncResult* _async_result; + GOutputStream* stream; + guint8* buffer; + gint buffer_length1; + gint length; + guint8* _tmp0_; + gint _tmp0__length1; + gssize i; + gssize _tmp1_; + gint _tmp2_; + gssize n; + GOutputStream* _tmp3_; + guint8* _tmp4_; + gint _tmp4__length1; + gssize _tmp5_; + gint _tmp6_; + gssize _tmp7_; + gssize _tmp8_; + GError* _tmp9_; + gssize _tmp10_; + gssize _tmp11_; + GError * _inner_error_; +}; + + + +static void spice_ctrl_input_stream_read_data_free (gpointer _data); +void spice_ctrl_input_stream_read (GInputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_input_stream_read_finish (GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_input_stream_read_co (SpiceCtrlInputStreamReadData* _data_); +static void spice_ctrl_input_stream_read_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); +static void spice_ctrl_output_stream_write_data_free (gpointer _data); +void spice_ctrl_output_stream_write (GOutputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_); +void spice_ctrl_output_stream_write_finish (GAsyncResult* _res_, GError** error); +static gboolean spice_ctrl_output_stream_write_co (SpiceCtrlOutputStreamWriteData* _data_); +static void spice_ctrl_output_stream_write_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); + + +static void spice_ctrl_input_stream_read_data_free (gpointer _data) { + SpiceCtrlInputStreamReadData* _data_; + _data_ = _data; + _g_object_unref0 (_data_->stream); + g_slice_free (SpiceCtrlInputStreamReadData, _data_); +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +void spice_ctrl_input_stream_read (GInputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlInputStreamReadData* _data_; + GInputStream* _tmp0_ = NULL; + GInputStream* _tmp1_ = NULL; + guint8* _tmp2_ = NULL; + gint _tmp2__length1 = 0; + _data_ = g_slice_new0 (SpiceCtrlInputStreamReadData); + _data_->_async_result = g_simple_async_result_new (NULL, _callback_, _user_data_, spice_ctrl_input_stream_read); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_input_stream_read_data_free); + _tmp0_ = stream; + _tmp1_ = _g_object_ref0 (_tmp0_); + _g_object_unref0 (_data_->stream); + _data_->stream = _tmp1_; + _tmp2_ = buffer; + _tmp2__length1 = buffer_length1; + _data_->buffer = _tmp2_; + _data_->buffer_length1 = _tmp2__length1; + spice_ctrl_input_stream_read_co (_data_); +} + + +void spice_ctrl_input_stream_read_finish (GAsyncResult* _res_, GError** error) { + SpiceCtrlInputStreamReadData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_input_stream_read_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlInputStreamReadData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_input_stream_read_co (_data_); +} + + +static gboolean spice_ctrl_input_stream_read_co (SpiceCtrlInputStreamReadData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + default: + g_assert_not_reached (); + } + _state_0: + _data_->_tmp0_ = NULL; + _data_->_tmp0__length1 = 0; + _data_->_tmp0_ = _data_->buffer; + _data_->_tmp0__length1 = _data_->buffer_length1; + _data_->length = _data_->_tmp0__length1; + _data_->i = (gssize) 0; + while (TRUE) { + _data_->_tmp1_ = 0L; + _data_->_tmp1_ = _data_->i; + _data_->_tmp2_ = 0; + _data_->_tmp2_ = _data_->length; + if (!(_data_->_tmp1_ < ((gssize) _data_->_tmp2_))) { + break; + } + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = _data_->stream; + _data_->_tmp4_ = NULL; + _data_->_tmp4__length1 = 0; + _data_->_tmp4_ = _data_->buffer; + _data_->_tmp4__length1 = _data_->buffer_length1; + _data_->_tmp5_ = 0L; + _data_->_tmp5_ = _data_->i; + _data_->_tmp6_ = 0; + _data_->_tmp6_ = _data_->length; + _data_->_state_ = 1; + g_input_stream_read_async (_data_->_tmp3_, _data_->_tmp4_ + ((gint) _data_->_tmp5_), (gsize) (_data_->_tmp6_ - ((gint) _data_->_tmp5_)), G_PRIORITY_DEFAULT, NULL, spice_ctrl_input_stream_read_ready, _data_); + return FALSE; + _state_1: + _data_->_tmp7_ = 0L; + _data_->_tmp7_ = g_input_stream_read_finish (_data_->_tmp3_, _data_->_res_, &_data_->_inner_error_); + _data_->n = _data_->_tmp7_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + if (_data_->_inner_error_->domain == G_IO_ERROR) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } else { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error_->message, g_quark_to_string (_data_->_inner_error_->domain), _data_->_inner_error_->code); + g_clear_error (&_data_->_inner_error_); + return FALSE; + } + } + _data_->_tmp8_ = 0L; + _data_->_tmp8_ = _data_->n; + if (_data_->_tmp8_ == ((gssize) 0)) { + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "closed stream"); + _data_->_inner_error_ = _data_->_tmp9_; + if (_data_->_inner_error_->domain == G_IO_ERROR) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } else { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error_->message, g_quark_to_string (_data_->_inner_error_->domain), _data_->_inner_error_->code); + g_clear_error (&_data_->_inner_error_); + return FALSE; + } + } + _data_->_tmp10_ = 0L; + _data_->_tmp10_ = _data_->i; + _data_->_tmp11_ = 0L; + _data_->_tmp11_ = _data_->n; + _data_->i = _data_->_tmp10_ + _data_->_tmp11_; + } + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + +static void spice_ctrl_output_stream_write_data_free (gpointer _data) { + SpiceCtrlOutputStreamWriteData* _data_; + _data_ = _data; + _g_object_unref0 (_data_->stream); + _data_->buffer = (g_free (_data_->buffer), NULL); + g_slice_free (SpiceCtrlOutputStreamWriteData, _data_); +} + + +void spice_ctrl_output_stream_write (GOutputStream* stream, guint8* buffer, int buffer_length1, GAsyncReadyCallback _callback_, gpointer _user_data_) { + SpiceCtrlOutputStreamWriteData* _data_; + GOutputStream* _tmp0_ = NULL; + GOutputStream* _tmp1_ = NULL; + _data_ = g_slice_new0 (SpiceCtrlOutputStreamWriteData); + _data_->_async_result = g_simple_async_result_new (NULL, _callback_, _user_data_, spice_ctrl_output_stream_write); + g_simple_async_result_set_op_res_gpointer (_data_->_async_result, _data_, spice_ctrl_output_stream_write_data_free); + _tmp0_ = stream; + _tmp1_ = _g_object_ref0 (_tmp0_); + _g_object_unref0 (_data_->stream); + _data_->stream = _tmp1_; + _data_->buffer = (g_free (_data_->buffer), NULL); + _data_->buffer = buffer; + _data_->buffer_length1 = buffer_length1; + spice_ctrl_output_stream_write_co (_data_); +} + + +void spice_ctrl_output_stream_write_finish (GAsyncResult* _res_, GError** error) { + SpiceCtrlOutputStreamWriteData* _data_; + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (_res_), error)) { + return; + } + _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); +} + + +static void spice_ctrl_output_stream_write_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_) { + SpiceCtrlOutputStreamWriteData* _data_; + _data_ = _user_data_; + _data_->_source_object_ = source_object; + _data_->_res_ = _res_; + spice_ctrl_output_stream_write_co (_data_); +} + + +static gboolean spice_ctrl_output_stream_write_co (SpiceCtrlOutputStreamWriteData* _data_) { + switch (_data_->_state_) { + case 0: + goto _state_0; + case 1: + goto _state_1; + default: + g_assert_not_reached (); + } + _state_0: + _data_->_tmp0_ = NULL; + _data_->_tmp0__length1 = 0; + _data_->_tmp0_ = _data_->buffer; + _data_->_tmp0__length1 = _data_->buffer_length1; + _data_->length = _data_->_tmp0__length1; + _data_->i = (gssize) 0; + while (TRUE) { + _data_->_tmp1_ = 0L; + _data_->_tmp1_ = _data_->i; + _data_->_tmp2_ = 0; + _data_->_tmp2_ = _data_->length; + if (!(_data_->_tmp1_ < ((gssize) _data_->_tmp2_))) { + break; + } + _data_->_tmp3_ = NULL; + _data_->_tmp3_ = _data_->stream; + _data_->_tmp4_ = NULL; + _data_->_tmp4__length1 = 0; + _data_->_tmp4_ = _data_->buffer; + _data_->_tmp4__length1 = _data_->buffer_length1; + _data_->_tmp5_ = 0L; + _data_->_tmp5_ = _data_->i; + _data_->_tmp6_ = 0; + _data_->_tmp6_ = _data_->length; + _data_->_state_ = 1; + g_output_stream_write_async (_data_->_tmp3_, _data_->_tmp4_ + ((gint) _data_->_tmp5_), (gsize) (_data_->_tmp6_ - ((gint) _data_->_tmp5_)), G_PRIORITY_DEFAULT, NULL, spice_ctrl_output_stream_write_ready, _data_); + return FALSE; + _state_1: + _data_->_tmp7_ = 0L; + _data_->_tmp7_ = g_output_stream_write_finish (_data_->_tmp3_, _data_->_res_, &_data_->_inner_error_); + _data_->n = _data_->_tmp7_; + if (G_UNLIKELY (_data_->_inner_error_ != NULL)) { + if (_data_->_inner_error_->domain == G_IO_ERROR) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->buffer = (g_free (_data_->buffer), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } else { + _data_->buffer = (g_free (_data_->buffer), NULL); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error_->message, g_quark_to_string (_data_->_inner_error_->domain), _data_->_inner_error_->code); + g_clear_error (&_data_->_inner_error_); + return FALSE; + } + } + _data_->_tmp8_ = 0L; + _data_->_tmp8_ = _data_->n; + if (_data_->_tmp8_ == ((gssize) 0)) { + _data_->_tmp9_ = NULL; + _data_->_tmp9_ = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "closed stream"); + _data_->_inner_error_ = _data_->_tmp9_; + if (_data_->_inner_error_->domain == G_IO_ERROR) { + g_simple_async_result_set_from_error (_data_->_async_result, _data_->_inner_error_); + g_error_free (_data_->_inner_error_); + _data_->buffer = (g_free (_data_->buffer), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; + } else { + _data_->buffer = (g_free (_data_->buffer), NULL); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error_->message, g_quark_to_string (_data_->_inner_error_->domain), _data_->_inner_error_->code); + g_clear_error (&_data_->_inner_error_); + return FALSE; + } + } + _data_->_tmp10_ = 0L; + _data_->_tmp10_ = _data_->i; + _data_->_tmp11_ = 0L; + _data_->_tmp11_ = _data_->n; + _data_->i = _data_->_tmp10_ + _data_->_tmp11_; + } + _data_->buffer = (g_free (_data_->buffer), NULL); + if (_data_->_state_ == 0) { + g_simple_async_result_complete_in_idle (_data_->_async_result); + } else { + g_simple_async_result_complete (_data_->_async_result); + } + g_object_unref (_data_->_async_result); + return FALSE; +} + + + diff --git a/src/controller/util.vala b/src/controller/util.vala new file mode 100644 index 0000000..acd677e --- /dev/null +++ b/src/controller/util.vala @@ -0,0 +1,42 @@ +// Copyright (C) 2012 Red Hat, Inc. + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . + +namespace SpiceCtrl { + + public async void input_stream_read (InputStream stream, uint8[] buffer) throws GLib.IOError { + var length = buffer.length; + ssize_t i = 0; + + while (i < length) { + var n = yield stream.read_async (buffer[i:length]); + if (n == 0) + throw new GLib.IOError.CLOSED ("closed stream") ; + i += n; + } + } + + public async void output_stream_write (OutputStream stream, owned uint8[] buffer) throws GLib.IOError { + var length = buffer.length; + ssize_t i = 0; + + while (i < length) { + var n = yield stream.write_async (buffer[i:length]); + if (n == 0) + throw new GLib.IOError.CLOSED ("closed stream") ; + i += n; + } + } + +} diff --git a/src/controller/win32-util.c b/src/controller/win32-util.c new file mode 100644 index 0000000..c3e0400 --- /dev/null +++ b/src/controller/win32-util.c @@ -0,0 +1,161 @@ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" +#include "win32-util.h" +#include +#include +#include + +gboolean +spice_win32_set_low_integrity (void* handle, GError **error) +{ + g_return_val_if_fail (handle != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* see also http://msdn.microsoft.com/en-us/library/bb625960.aspx */ + PSECURITY_DESCRIPTOR psd = NULL; + PACL psacl = NULL; + BOOL sacl_present = FALSE; + BOOL sacl_defaulted = FALSE; + char *emsg; + int errsv; + gboolean success = FALSE; + + if (!ConvertStringSecurityDescriptorToSecurityDescriptor ("S:(ML;;NW;;;LW)", + SDDL_REVISION_1, &psd, NULL)) + goto failed; + + if (!GetSecurityDescriptorSacl (psd, &sacl_present, &psacl, &sacl_defaulted)) + goto failed; + + if (SetSecurityInfo (handle, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, + NULL, NULL, NULL, psacl) != ERROR_SUCCESS) + goto failed; + + success = TRUE; + goto end; + +failed: + errsv = GetLastError (); + emsg = g_win32_error_message (errsv); + g_set_error (error, G_IO_ERROR, + g_io_error_from_win32_error (errsv), + "Error setting integrity: %s", + emsg); + g_free (emsg); + +end: + if (psd != NULL) + LocalFree (psd); + + return success; +} + +static gboolean +get_user_security_attributes (SECURITY_ATTRIBUTES* psa, SECURITY_DESCRIPTOR* psd, PACL* ppdacl) +{ + EXPLICIT_ACCESS ea; + TRUSTEE trst; + DWORD ret = 0; + + ZeroMemory (psa, sizeof (*psa)); + ZeroMemory (psd, sizeof (*psd)); + psa->nLength = sizeof (*psa); + psa->bInheritHandle = FALSE; + psa->lpSecurityDescriptor = psd; + + ZeroMemory (&trst, sizeof (trst)); + trst.pMultipleTrustee = NULL; + trst.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + trst.TrusteeForm = TRUSTEE_IS_NAME; + trst.TrusteeType = TRUSTEE_IS_USER; + trst.ptstrName = "CURRENT_USER"; + + ZeroMemory (&ea, sizeof (ea)); + ea.grfAccessPermissions = GENERIC_WRITE | GENERIC_READ; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee = trst; + + ret = SetEntriesInAcl (1, &ea, NULL, ppdacl); + if (ret != ERROR_SUCCESS) + return FALSE; + + if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION)) + return FALSE; + + if (!SetSecurityDescriptorDacl (psd, TRUE, *ppdacl, FALSE)) + return FALSE; + + return TRUE; +} + +#define DEFAULT_PIPE_BUF_SIZE 4096 + +SpiceNamedPipe* +spice_win32_user_pipe_new (gchar *name, GError **error) +{ + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; + PACL dacl = NULL; + HANDLE pipe; + SpiceNamedPipe *np = NULL; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + + if (!get_user_security_attributes (&sa, &sd, &dacl)) + return NULL; + + pipe = CreateNamedPipe (name, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | + /* FIXME: why is FILE_FLAG_FIRST_PIPE_INSTANCE needed for WRITE_DAC + * (apparently needed by SetSecurityInfo). This will prevent + * multiple pipe listener....?! */ + FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + DEFAULT_PIPE_BUF_SIZE, DEFAULT_PIPE_BUF_SIZE, + 0, &sa); + + if (pipe == INVALID_HANDLE_VALUE) { + int errsv = GetLastError (); + gchar *emsg = g_win32_error_message (errsv); + + g_set_error (error, + G_IO_ERROR, + g_io_error_from_win32_error (errsv), + "Error CreateNamedPipe(): %s", + emsg); + + g_free (emsg); + goto end; + } + + /* lower integrity on Vista/Win7+ */ + if ((LOBYTE (g_win32_get_windows_version()) > 0x05) && + !spice_win32_set_low_integrity (pipe, error)) + goto end; + + np = SPICE_NAMED_PIPE (g_initable_new (SPICE_TYPE_NAMED_PIPE, + NULL, error, "handle", pipe, NULL)); + +end: + LocalFree (dacl); + + return np; +} diff --git a/src/controller/win32-util.h b/src/controller/win32-util.h new file mode 100644 index 0000000..b24ac77 --- /dev/null +++ b/src/controller/win32-util.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __WIN32_UTIL_H__ +#define __WIN32_UTIL_H__ + +#include +#include "namedpipe.h" + +G_BEGIN_DECLS + +gboolean spice_win32_set_low_integrity (void* handle, GError **error); +SpiceNamedPipe* spice_win32_user_pipe_new (gchar *name, GError **error); + +G_END_DECLS + +#endif /* __WIN32_UTIL_H__ */ diff --git a/src/coroutine.h b/src/coroutine.h new file mode 100644 index 0000000..78dc467 --- /dev/null +++ b/src/coroutine.h @@ -0,0 +1,83 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COROUTINE_H_ +#define _COROUTINE_H_ + +#include "config.h" + +#if WITH_UCONTEXT +#include "continuation.h" +#elif WITH_WINFIBER +#include +#else +#include +#endif + +struct coroutine +{ + size_t stack_size; + void *(*entry)(void *); + int (*release)(struct coroutine *); + + /* read-only */ + int exited; + + /* private */ + struct coroutine *caller; + void *data; + +#if WITH_UCONTEXT + struct continuation cc; +#elif WITH_WINFIBER + LPVOID fiber; + int ret; +#else + GThread *thread; + gboolean runnable; +#endif +}; + +void coroutine_init(struct coroutine *co); + +int coroutine_release(struct coroutine *co); + +void *coroutine_swap(struct coroutine *from, struct coroutine *to, void *arg); + +struct coroutine *coroutine_self(void); + +void *coroutine_yieldto(struct coroutine *to, void *arg); + +void *coroutine_yield(void *arg); + +gboolean coroutine_is_main(struct coroutine *co); + +static inline gboolean coroutine_self_is_main(void) { + return coroutine_self() == NULL || coroutine_is_main(coroutine_self()); +} + +#endif +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/coroutine_gthread.c b/src/coroutine_gthread.c new file mode 100644 index 0000000..b0098fa --- /dev/null +++ b/src/coroutine_gthread.c @@ -0,0 +1,170 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "coroutine.h" +#include +#include + +static GCond *run_cond; +static GMutex *run_lock; +static struct coroutine *current; +static struct coroutine leader; + +#if 0 +#define CO_DEBUG(OP) fprintf(stderr, "%s %p %s %d\n", OP, g_thread_self(), __FUNCTION__, __LINE__) +#else +#define CO_DEBUG(OP) +#endif + +static void coroutine_system_init(void) +{ + if (!g_thread_supported()) { + CO_DEBUG("INIT"); + g_thread_init(NULL); + } + + + run_cond = g_cond_new(); + run_lock = g_mutex_new(); + CO_DEBUG("LOCK"); + g_mutex_lock(run_lock); + + /* The thread that creates the first coroutine is the system coroutine + * so let's fill out a structure for it */ + leader.entry = NULL; + leader.release = NULL; + leader.stack_size = 0; + leader.exited = 0; + leader.thread = g_thread_self(); + leader.runnable = TRUE; /* we're the one running right now */ + leader.caller = NULL; + leader.data = NULL; + + current = &leader; +} + +static gpointer coroutine_thread(gpointer opaque) +{ + struct coroutine *co = opaque; + CO_DEBUG("LOCK"); + g_mutex_lock(run_lock); + while (!co->runnable) { + CO_DEBUG("WAIT"); + g_cond_wait(run_cond, run_lock); + } + + CO_DEBUG("RUNNABLE"); + current = co; + co->caller->data = co->entry(co->data); + co->exited = 1; + + co->caller->runnable = TRUE; + CO_DEBUG("BROADCAST"); + g_cond_broadcast(run_cond); + CO_DEBUG("UNLOCK"); + g_mutex_unlock(run_lock); + + return NULL; +} + +void coroutine_init(struct coroutine *co) +{ + GError *err = NULL; + + if (run_cond == NULL) + coroutine_system_init(); + + CO_DEBUG("NEW"); + co->thread = g_thread_create_full(coroutine_thread, co, co->stack_size, + FALSE, TRUE, + G_THREAD_PRIORITY_NORMAL, + &err); + if (err != NULL) + g_error("g_thread_create_full() failed: %s", err->message); + + co->exited = 0; + co->runnable = FALSE; + co->caller = NULL; +} + +int coroutine_release(struct coroutine *co G_GNUC_UNUSED) +{ + return 0; +} + +void *coroutine_swap(struct coroutine *from, struct coroutine *to, void *arg) +{ + from->runnable = FALSE; + to->runnable = TRUE; + to->data = arg; + to->caller = from; + CO_DEBUG("BROADCAST"); + g_cond_broadcast(run_cond); + CO_DEBUG("UNLOCK"); + g_mutex_unlock(run_lock); + CO_DEBUG("LOCK"); + g_mutex_lock(run_lock); + while (!from->runnable) { + CO_DEBUG("WAIT"); + g_cond_wait(run_cond, run_lock); + } + current = from; + to->caller = NULL; + + CO_DEBUG("SWAPPED"); + return from->data; +} + +struct coroutine *coroutine_self(void) +{ + if (run_cond == NULL) + coroutine_system_init(); + + return current; +} + +void *coroutine_yieldto(struct coroutine *to, void *arg) +{ + g_return_val_if_fail(!to->caller, NULL); + g_return_val_if_fail(!to->exited, NULL); + + CO_DEBUG("SWAP"); + return coroutine_swap(coroutine_self(), to, arg); +} + +void *coroutine_yield(void *arg) +{ + struct coroutine *to = coroutine_self()->caller; + if (!to) { + fprintf(stderr, "Co-routine is yielding to no one\n"); + abort(); + } + + CO_DEBUG("SWAP"); + coroutine_self()->caller = NULL; + return coroutine_swap(coroutine_self(), to, arg); +} + +gboolean coroutine_is_main(struct coroutine *co) +{ + return (co == &leader); +} diff --git a/src/coroutine_ucontext.c b/src/coroutine_ucontext.c new file mode 100644 index 0000000..d709a33 --- /dev/null +++ b/src/coroutine_ucontext.c @@ -0,0 +1,150 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include +#include "coroutine.h" + +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif + +int coroutine_release(struct coroutine *co) +{ + return cc_release(&co->cc); +} + +static int _coroutine_release(struct continuation *cc) +{ + struct coroutine *co = container_of(cc, struct coroutine, cc); + + if (co->release) { + int ret = co->release(co); + if (ret < 0) + return ret; + } + + munmap(co->cc.stack, co->cc.stack_size); + + co->caller = NULL; + + return 0; +} + +static void coroutine_trampoline(struct continuation *cc) +{ + struct coroutine *co = container_of(cc, struct coroutine, cc); + co->data = co->entry(co->data); +} + +void coroutine_init(struct coroutine *co) +{ + if (co->stack_size == 0) + co->stack_size = 16 << 20; + + co->cc.stack_size = co->stack_size; + co->cc.stack = mmap(0, co->stack_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (co->cc.stack == MAP_FAILED) + g_error("mmap(%" G_GSIZE_FORMAT ") failed: %s", + co->stack_size, g_strerror(errno)); + + co->cc.entry = coroutine_trampoline; + co->cc.release = _coroutine_release; + co->exited = 0; + + cc_init(&co->cc); +} + +#if 0 +static __thread struct coroutine leader; +static __thread struct coroutine *current; +#else +static struct coroutine leader; +static struct coroutine *current; +#endif + +struct coroutine *coroutine_self(void) +{ + if (current == NULL) + current = &leader; + return current; +} + +void *coroutine_swap(struct coroutine *from, struct coroutine *to, void *arg) +{ + int ret; + to->data = arg; + current = to; + ret = cc_swap(&from->cc, &to->cc); + if (ret == 0) + return from->data; + else if (ret == 1) { + coroutine_release(to); + current = from; + to->exited = 1; + return to->data; + } + + return NULL; +} + +void *coroutine_yieldto(struct coroutine *to, void *arg) +{ + g_return_val_if_fail(!to->caller, NULL); + g_return_val_if_fail(!to->exited, NULL); + + to->caller = coroutine_self(); + return coroutine_swap(coroutine_self(), to, arg); +} + +void *coroutine_yield(void *arg) +{ + struct coroutine *to = coroutine_self()->caller; + if (!to) { + fprintf(stderr, "Co-routine is yielding to no one\n"); + abort(); + } + coroutine_self()->caller = NULL; + return coroutine_swap(coroutine_self(), to, arg); +} + +gboolean coroutine_is_main(struct coroutine *co) +{ + return (co == &leader); +} +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/coroutine_winfibers.c b/src/coroutine_winfibers.c new file mode 100644 index 0000000..a56d33d --- /dev/null +++ b/src/coroutine_winfibers.c @@ -0,0 +1,126 @@ +/* + * SpiceGtk coroutine with Windows fibers + * + * Copyright (C) 2011 Marc-André Lureau + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include +#include + +#include "coroutine.h" + +static struct coroutine leader = { 0, }; +static struct coroutine *current = NULL; +static struct coroutine *caller = NULL; + +int coroutine_release(struct coroutine *co) +{ + DeleteFiber(co->fiber); + return 0; +} + +static void WINAPI coroutine_trampoline(LPVOID lpParameter) +{ + struct coroutine *co = (struct coroutine *)lpParameter; + + co->data = co->entry(co->data); + + if (co->release) + co->ret = co->release(co); + else + co->ret = 0; + + co->caller = NULL; + + // and switch back to caller + co->ret = 1; + SwitchToFiber(caller->fiber); +} + +void coroutine_init(struct coroutine *co) +{ + if (leader.fiber == NULL) { + leader.fiber = ConvertThreadToFiber(&leader); + if (leader.fiber == NULL) + g_error("ConvertThreadToFiber() failed"); + } + + co->exited = 0; + co->fiber = CreateFiber(0, &coroutine_trampoline, co); + if (co->fiber == NULL) + g_error("CreateFiber() failed"); + + co->ret = 0; +} + +struct coroutine *coroutine_self(void) +{ + if (current == NULL) + current = &leader; + return current; +} + +void *coroutine_swap(struct coroutine *from, struct coroutine *to, void *arg) +{ + to->data = arg; + current = to; + caller = from; + SwitchToFiber(to->fiber); + if (to->ret == 0) + return from->data; + else if (to->ret == 1) { + coroutine_release(to); + current = &leader; + to->exited = 1; + return to->data; + } + + return NULL; +} + +void *coroutine_yieldto(struct coroutine *to, void *arg) +{ + g_return_val_if_fail(!to->caller, NULL); + g_return_val_if_fail(!to->exited, NULL); + + to->caller = coroutine_self(); + return coroutine_swap(coroutine_self(), to, arg); +} + +void *coroutine_yield(void *arg) +{ + struct coroutine *to = coroutine_self()->caller; + if (!to) { + fprintf(stderr, "Co-routine is yielding to no one\n"); + abort(); + } + coroutine_self()->caller = NULL; + return coroutine_swap(coroutine_self(), to, arg); +} + +gboolean coroutine_is_main(struct coroutine *co) +{ + return (co == &leader); +} +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/decode-glz-tmpl.c b/src/decode-glz-tmpl.c new file mode 100644 index 0000000..b337a8b --- /dev/null +++ b/src/decode-glz-tmpl.c @@ -0,0 +1,336 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +// External defines: PLT, RGBX/PLTXX/ALPHA, TO_RGB32. +// If PLT4/1 and TO_RGB32 are defined, we need CAST_PLT_DISTANCE ( +// because then the number of pixels differ from the units used in the compression) + +/* + For each output pixel type the following macros are defined: + OUT_PIXEL - the output pixel type + COPY_PIXEL(p, out) - assigns the pixel to the place pointed by out and + increases out. Used in RLE. + Need special handling because in alpha we copy only + the pad byte. + COPY_REF_PIXEL(ref, out) - copies the pixel pointed by ref to the pixel pointed by out. + Increases ref and out. + COPY_COMP_PIXEL(encoder, out) - copies pixel from the compressed buffer to the decompressed + buffer. Increases out. +*/ + +#if !defined(LZ_RGB_ALPHA) +#define COPY_PIXEL(p, out) (*(out++) = p) +#define COPY_REF_PIXEL(ref, out) (*(out++) = *(ref++)) +#endif + +// decompressing plt to plt +#ifdef LZ_PLT +#ifndef TO_RGB32 +#define OUT_PIXEL one_byte_pixel_t +#define FNAME(name) glz_plt_##name +#define COPY_COMP_PIXEL(in, out) {(out)->a = *(in++); out++;} +#else // TO_RGB32 +#define OUT_PIXEL rgb32_pixel_t +#define COPY_PLT_ENTRY(ent, out) {\ + (out)->b = ent; (out)->g = (ent >> 8); (out)->r = (ent >> 16); (out)->pad = 0;} +#ifdef PLT8 +#define FNAME(name) glz_plt8_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out, palette) { \ + uint32_t rgb = palette->ents[*(in++)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ +} +#elif defined(PLT4_BE) +#define FNAME(name) glz_plt4_be_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out, palette){ \ + uint8_t byte = *(in++); \ + uint32_t rgb = palette->ents[((byte >> 4) & 0x0f) % (palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ + rgb = palette->ents[(byte & 0x0f) % (palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ +} +#define CAST_PLT_DISTANCE(dist) (dist*2) +#elif defined(PLT4_LE) +#define FNAME(name) glz_plt4_le_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out, palette){ \ + uint8_t byte = *(in++); \ + uint32_t rgb = palette->ents[(byte & 0x0f) % (palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ + rgb = palette->ents[((byte >> 4) & 0x0f) % (palette->num_ents)]; \ + COPY_PLT_ENTRY(rgb, out); \ + out++; \ +} +#define CAST_PLT_DISTANCE(dist) (dist*2) +#elif defined(PLT1_BE) // TODO store palette entries for direct access +#define FNAME(name) glz_plt1_be_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out, palette){ \ + uint8_t byte = *(in++); \ + int i; \ + uint32_t fore = palette->ents[1]; \ + uint32_t back = palette->ents[0]; \ + for (i = 7; i >= 0; i--) \ + { \ + if ((byte >> i) & 1) { \ + COPY_PLT_ENTRY(fore, out); \ + } else { \ + COPY_PLT_ENTRY(back, out); \ + } \ + out++; \ + } \ +} +#define CAST_PLT_DISTANCE(dist) (dist*8) +#elif defined(PLT1_LE) +#define FNAME(name) glz_plt1_le_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out, palette){ \ + uint8_t byte = *(in++); \ + int i; \ + uint32_t fore = palette->ents[1]; \ + uint32_t back = palette->ents[0]; \ + for (i = 0; i < 8; i++) \ + { \ + if ((byte >> i) & 1) { \ + COPY_PLT_ENTRY(fore, out); \ + } else { \ + COPY_PLT_ENTRY(back, out); \ + } \ + out++; \ + } \ +} +#define CAST_PLT_DISTANCE(dist) (dist*8) +#endif // PLT Type +#endif // TO_RGB32 +#endif + +#ifdef LZ_RGB16 +#ifndef TO_RGB32 +#define OUT_PIXEL rgb16_pixel_t +#define FNAME(name) glz_rgb16_##name +#define COPY_COMP_PIXEL(in, out) {*out = (*(in++)) << 8; *out |= *(in++); out++;} +#else +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) glz_rgb16_to_rgb32_##name +#define COPY_COMP_PIXEL(in, out) {out->r = *(in++); out->b= *(in++); \ + out->g = (((out->r) << 6) | ((out->b) >> 2)) & ~0x07; \ + out->g |= (out->g >> 5); \ + out->r = ((out->r << 1) & ~0x07) | ((out->r >> 4) & 0x07) ; \ + out->b = (out->b << 3) | ((out->b >> 2) & 0x07); \ + out->pad = 0; \ + out++; \ +} +#endif +#endif + +#ifdef LZ_RGB24 +#define OUT_PIXEL rgb24_pixel_t +#define FNAME(name) glz_rgb24_##name +#define COPY_COMP_PIXEL(in, out) { \ + out->b = *(in++); \ + out->g = *(in++); \ + out->r = *(in++); \ + out++; \ +} +#endif + +#ifdef LZ_RGB32 +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) glz_rgb32_##name +#define COPY_COMP_PIXEL(in, out) { \ + out->b = *(in++); \ + out->g = *(in++); \ + out->r = *(in++); \ + out->pad = 0; \ + out++; \ +} +#endif + +#ifdef LZ_RGB_ALPHA +#define OUT_PIXEL rgb32_pixel_t +#define FNAME(name) glz_rgb_alpha_##name +#define COPY_PIXEL(p, out) {out->pad = p.pad; out++;} +#define COPY_REF_PIXEL(ref, out) {out->pad = ref->pad; out++; ref++;} +#define COPY_COMP_PIXEL(in, out) {out->pad = *(in++); out++;} +#endif + +// TODO: separate into routines that decode to dist,len. and to a routine that +// actually copies the data. + +/* returns num of bytes read from in buf. + size should be in PIXEL */ +static size_t FNAME(decode)(SpiceGlzDecoderWindow *window, + uint8_t* in_buf, uint8_t *out_buf, int size, + uint64_t image_id, SpicePalette *plt) +{ + uint8_t *ip = in_buf; + OUT_PIXEL *out_pix_buf = (OUT_PIXEL *)out_buf; + OUT_PIXEL *op = out_pix_buf; + OUT_PIXEL *op_limit = out_pix_buf + size; + + uint32_t ctrl = *(ip++); + int loop = true; + + do { + if (ctrl >= MAX_COPY) { // reference (dictionary/RLE) + OUT_PIXEL *ref = op; + uint32_t len = ctrl >> 5; + uint8_t pixel_flag = (ctrl >> 4) & 0x01; + uint32_t pixel_ofs = (ctrl & 0x0f); + uint8_t image_flag; + uint32_t image_dist; + + /* retrieving the referenced images, the offset of the first pixel, + and the match length */ + + uint8_t code; + //len--; // TODO: why do we do this? + + if (len == 7) { // match length is bigger than 7 + do { + code = *(ip++); + len += code; + } while (code == 255); // remaining of len + } + code = *(ip++); + pixel_ofs += (code << 4); + + code = *(ip++); + image_flag = (code >> 6) & 0x03; + if (!pixel_flag) { // short pixel offset + int i; + image_dist = code & 0x3f; + for (i = 0; i < image_flag; i++) { + code = *(ip++); + image_dist += (code << (6 + (8 * i))); + } + } else { + int i; + pixel_flag = (code >> 5) & 0x01; + pixel_ofs += (code & 0x1f) << 12; + image_dist = 0; + for (i = 0; i < image_flag; i++) { + code = *(ip++); + image_dist += (code << 8 * i); + } + + + if (pixel_flag) { // very long pixel offset + code = *(ip++); + pixel_ofs += code << 17; + } + } + +#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) + len += 2; // length is biased by 2 (fixing bias) +#elif defined(LZ_RGB16) + len += 1; // length is biased by 1 (fixing bias) +#endif + if (!image_dist) { + pixel_ofs += 1; // offset is biased by 1 (fixing bias) + } + +#if defined(TO_RGB32) +#if defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || defined(PLT1_LE) + pixel_ofs = CAST_PLT_DISTANCE(pixel_ofs); + len = CAST_PLT_DISTANCE(len); +#endif +#endif + + if (!image_dist) { // reference is inside the same image + ref -= pixel_ofs; + g_return_val_if_fail(ref + len <= op_limit, 0); + g_return_val_if_fail(ref >= out_pix_buf, 0); + } else { + ref = glz_decoder_window_bits(window, image_id, + image_dist, pixel_ofs); + } + + g_return_val_if_fail(ref != NULL, 0); + g_return_val_if_fail(op + len <= op_limit, 0); + + /* copying the match*/ + + if (ref == (op - 1)) { // run (this will never be called in PLT4/1_TO_RGB because the + // number of pixel copied is larger then one... + /* optimize copy for a run */ + OUT_PIXEL b = *ref; + for (; len; --len) { + COPY_PIXEL(b, op); + g_return_val_if_fail(op <= op_limit, 0); + } + } else { + for (; len; --len) { + COPY_REF_PIXEL(ref, op); + g_return_val_if_fail(op <= op_limit, 0); + } + } + } else { // copy + ctrl++; // copy count is biased by 1 +#if defined(TO_RGB32) && (defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || \ + defined(PLT1_LE)) + g_return_val_if_fail(op + CAST_PLT_DISTANCE(ctrl) <= op_limit, 0); +#else + g_return_val_if_fail(op + ctrl <= op_limit, 0); +#endif + +#if defined(TO_RGB32) && defined(LZ_PLT) + g_return_val_if_fail(plt, 0); + COPY_COMP_PIXEL(ip, op, plt); +#else + COPY_COMP_PIXEL(ip, op); +#endif + g_return_val_if_fail(op <= op_limit, 0); + + for (--ctrl; ctrl; ctrl--) { +#if defined(TO_RGB32) && defined(LZ_PLT) + g_return_val_if_fail(plt, 0); + COPY_COMP_PIXEL(ip, op, plt); +#else + COPY_COMP_PIXEL(ip, op); +#endif + g_return_val_if_fail(op <= op_limit, 0); + } + } // END REF/COPY + + if (LZ_EXPECT_CONDITIONAL(op < op_limit)) { + ctrl = *(ip++); + } else { + loop = false; + } + } while (LZ_EXPECT_CONDITIONAL(loop)); + + return (ip - in_buf); +} +#undef LZ_PLT +#undef PLT8 +#undef PLT4_BE +#undef PLT4_LE +#undef PLT1_BE +#undef PLT1_LE +#undef LZ_RGB16 +#undef LZ_RGB24 +#undef LZ_RGB32 +#undef LZ_RGB_ALPHA +#undef TO_RGB32 +#undef OUT_PIXEL +#undef FNAME +#undef COPY_PIXEL +#undef COPY_REF_PIXEL +#undef COPY_COMP_PIXEL +#undef COPY_PLT_ENTRY +#undef CAST_PLT_DISTANCE diff --git a/src/decode-glz.c b/src/decode-glz.c new file mode 100644 index 0000000..d5b72ab --- /dev/null +++ b/src/decode-glz.c @@ -0,0 +1,474 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#include + +#include + +#include "gio-coroutine.h" +#include "spice-util.h" +#include "decode.h" + +#include "common/canvas_utils.h" + +struct glz_image_hdr { + uint64_t id; + LzImageType type; + uint32_t width; + uint32_t height; + uint32_t gross_pixels; + bool top_down; + uint32_t win_head_dist; +}; + +struct glz_image { + struct glz_image_hdr hdr; + pixman_image_t *surface; + uint8_t *data; +}; + +static struct glz_image *glz_image_new(struct glz_image_hdr *hdr, + int type, void *opaque) +{ + struct glz_image *img; + + g_return_val_if_fail(type == LZ_IMAGE_TYPE_RGB32 || type == LZ_IMAGE_TYPE_RGBA, NULL); + + img = g_new0(struct glz_image, 1); + img->hdr = *hdr; + img->surface = alloc_lz_image_surface + (opaque, type == LZ_IMAGE_TYPE_RGBA ? PIXMAN_LE_a8r8g8b8 : PIXMAN_LE_x8r8g8b8, + img->hdr.width, img->hdr.height, img->hdr.gross_pixels, img->hdr.top_down); + pixman_image_ref(img->surface); + img->data = (uint8_t *)pixman_image_get_data(img->surface); + if (!img->hdr.top_down) { + img->data = img->data - img->hdr.width * (img->hdr.height - 1) * 4; + } + return img; +} + +static void glz_image_destroy(struct glz_image *img) +{ + if (img == NULL) + return; + + pixman_image_unref(img->surface); + free(img); +} + +/* ------------------------------------------------------------------ */ + +#define INIT_IMAGES_CAPACITY 100 +#define WIN_OVERFLOW_FACTOR 1.5 +#define WIN_REALLOC_FACTOR 1.5 + +struct SpiceGlzDecoderWindow { + struct glz_image **images; + uint32_t nimages; + uint64_t oldest; + uint64_t tail_gap; +}; + +static void glz_decoder_window_resize(SpiceGlzDecoderWindow *w) +{ + struct glz_image **new_images; + int i, new_slot; + + SPICE_DEBUG("%s: array resize %u -> %u", __FUNCTION__, + w->nimages, w->nimages * 2); + new_images = g_new0(struct glz_image*, w->nimages * 2); + for (i = 0; i < w->nimages; i++) { + if (w->images[i] == NULL) { + /* + * We can have empty slots when images come in out of order, this + * can happen when a vm has multiple displays, since each display + * uses its own socket there is no guarantee that images + * originating from different displays are received in id order. + */ + continue; + } + new_slot = w->images[i]->hdr.id % (w->nimages * 2); + new_images[new_slot] = w->images[i]; + } + free(w->images); + w->images = new_images; + w->nimages *= 2; +} + +static void glz_decoder_window_add(SpiceGlzDecoderWindow *w, + struct glz_image *img) +{ + int slot = img->hdr.id % w->nimages; + + if (w->images[slot]) { + /* need more space */ + glz_decoder_window_resize(w); + slot = img->hdr.id % w->nimages; + } + + w->images[slot] = img; + + /* close the gap */ + while (w->tail_gap <= img->hdr.id && w->images[w->tail_gap % w->nimages] != NULL) + w->tail_gap++; +} + +struct wait_for_image_data { + SpiceGlzDecoderWindow *window; + uint64_t id; +}; + +static gboolean wait_for_image(gpointer data) +{ + struct wait_for_image_data *wait = data; + int slot = wait->id % wait->window->nimages; + struct glz_image *image = wait->window->images[slot]; + gboolean ready = image && image->hdr.id == wait->id; + + return ready; +} + +static void *glz_decoder_window_bits(SpiceGlzDecoderWindow *w, uint64_t id, + uint32_t dist, uint32_t offset) +{ + struct wait_for_image_data data = { + .window = w, + .id = id - dist, + }; + + if (!g_coroutine_condition_wait(g_coroutine_self(), wait_for_image, &data)) + SPICE_DEBUG("wait for image cancelled"); + + int slot = (id - dist) % w->nimages; + + g_return_val_if_fail(w->images[slot] != NULL, NULL); + g_return_val_if_fail(w->images[slot]->hdr.id == id - dist, NULL); + g_return_val_if_fail(w->images[slot]->hdr.gross_pixels >= offset, NULL); + + return w->images[slot]->data + offset * 4; +} + +static void glz_decoder_window_release(SpiceGlzDecoderWindow *w, + uint64_t oldest) +{ + int slot; + + while (w->oldest < oldest) { + slot = w->oldest % w->nimages; + g_clear_pointer(&w->images[slot], glz_image_destroy); + w->oldest++; + } +} + +/* ------------------------------------------------------------------ */ + +typedef struct GlibGlzDecoder { + SpiceGlzDecoder base; + uint8_t *in_start; + uint8_t *in_now; + SpiceGlzDecoderWindow *window; + struct glz_image_hdr image; +} GlibGlzDecoder; + +/* + * Give hints to the compiler for branch prediction optimization. + */ +#if defined(__GNUC__) && (__GNUC__ > 2) +#define LZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) +#define LZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) +#else +#define LZ_EXPECT_CONDITIONAL(c) (c) +#define LZ_UNEXPECT_CONDITIONAL(c) (c) +#endif + + +#ifdef __GNUC__ +#define ATTR_PACKED __attribute__ ((__packed__)) +#else +#define ATTR_PACKED +#pragma pack(push) +#pragma pack(1) +#endif + +/* + * the palette images will be treated as one byte pixels. Their width + * should be transformed accordingly. + */ +typedef struct ATTR_PACKED one_byte_pixel_t { + uint8_t a; +} one_byte_pixel_t; + +typedef struct ATTR_PACKED rgb32_pixel_t { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t pad; +} rgb32_pixel_t; + +typedef struct ATTR_PACKED rgb24_pixel_t { + uint8_t b; + uint8_t g; + uint8_t r; +} rgb24_pixel_t; + +typedef uint16_t rgb16_pixel_t; + +#ifndef __GNUC__ +#pragma pack(pop) +#endif + +#undef ATTR_PACKED + +#define LZ_PLT +#include "decode-glz-tmpl.c" + +#define LZ_PLT +#define PLT8 +#define TO_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_PLT +#define PLT4_BE +#define TO_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_PLT +#define PLT4_LE +#define TO_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_PLT +#define PLT1_BE +#define TO_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_PLT +#define PLT1_LE +#define TO_RGB32 +#include "decode-glz-tmpl.c" + + +#define LZ_RGB16 +#include "decode-glz-tmpl.c" +#define LZ_RGB16 +#define TO_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_RGB24 +#include "decode-glz-tmpl.c" + +#define LZ_RGB32 +#include "decode-glz-tmpl.c" + +#define LZ_RGB_ALPHA +#include "decode-glz-tmpl.c" + +#undef LZ_UNEXPECT_CONDITIONAL +#undef LZ_EXPECT_CONDITIONAL + +typedef size_t (*decode_function)(SpiceGlzDecoderWindow *window, + uint8_t* in_buf, uint8_t *out_buf, int size, + uint64_t id, SpicePalette *plt); + +// ordered according to LZ_IMAGE_TYPE +const decode_function DECODE_TO_RGB32[] = { + NULL, + glz_plt1_le_to_rgb32_decode, + glz_plt1_be_to_rgb32_decode, + glz_plt4_le_to_rgb32_decode, + glz_plt4_be_to_rgb32_decode, + glz_plt8_to_rgb32_decode, + glz_rgb16_to_rgb32_decode, + glz_rgb32_decode, + glz_rgb32_decode, + glz_rgb32_decode +}; + +const decode_function DECODE_TO_SAME[] = { + NULL, + glz_plt_decode, + glz_plt_decode, + glz_plt_decode, + glz_plt_decode, + glz_plt_decode, + glz_rgb16_decode, + glz_rgb24_decode, + glz_rgb32_decode, + glz_rgb32_decode +}; + +static uint32_t decode_32(GlibGlzDecoder *d) +{ + uint32_t word = 0; + word |= *(d->in_now++); + word <<= 8; + word |= *(d->in_now++); + word <<= 8; + word |= *(d->in_now++); + word <<= 8; + word |= *(d->in_now++); + return word; +} + +static uint64_t decode_64(GlibGlzDecoder *d) +{ + uint64_t long_word = decode_32(d); + long_word <<= 32; + long_word |= decode_32(d); + return long_word; +} + +static void decode_header(GlibGlzDecoder *d) +{ + uint32_t magic; + uint32_t version; + uint32_t stride; + uint8_t tmp; + + magic = decode_32(d); + g_return_if_fail(magic == LZ_MAGIC); + + version = decode_32(d); + g_return_if_fail(version == LZ_VERSION); + + tmp = *(d->in_now++); + + d->image.type = (LzImageType)(tmp & LZ_IMAGE_TYPE_MASK); + d->image.top_down = (tmp >> LZ_IMAGE_TYPE_LOG) ? true : false; + d->image.width = decode_32(d); + d->image.height = decode_32(d); + stride = decode_32(d); + + if (IS_IMAGE_TYPE_PLT[d->image.type]) { + d->image.gross_pixels = stride * PLT_PIXELS_PER_BYTE[d->image.type] + * d->image.height; + } else { + d->image.gross_pixels = d->image.width * d->image.height; + } + + d->image.id = decode_64(d); + d->image.win_head_dist = decode_32(d); + + SPICE_DEBUG("%s: %ux%u, id %" PRIu64 ", ref %" PRIu64, + __FUNCTION__, + d->image.width, d->image.height, d->image.id, + d->image.id - d->image.win_head_dist); +} + +static void decode(SpiceGlzDecoder *decoder, + uint8_t *data, SpicePalette *palette, + void *usr_data) +{ + GlibGlzDecoder *d = SPICE_CONTAINEROF(decoder, GlibGlzDecoder, base); + LzImageType decoded_type; + struct glz_image *decoded_image; + size_t n_in_bytes_decoded; + + d->in_start = data; + d->in_now = data; + + decode_header(d); + + if (d->image.type == LZ_IMAGE_TYPE_RGBA) { + decoded_type = LZ_IMAGE_TYPE_RGBA; + } else { + decoded_type = LZ_IMAGE_TYPE_RGB32; + } + + decoded_image = glz_image_new(&d->image, decoded_type, usr_data); + + n_in_bytes_decoded = DECODE_TO_RGB32[d->image.type] + (d->window, d->in_now, decoded_image->data, + d->image.gross_pixels, d->image.id, palette); + + d->in_now += n_in_bytes_decoded; + + if (d->image.type == LZ_IMAGE_TYPE_RGBA) { + glz_rgb_alpha_decode(d->window, d->in_now, decoded_image->data, + d->image.gross_pixels, d->image.id, palette); + } + + glz_decoder_window_add(d->window, decoded_image); + + { /* release old images from last tail_gap, only if the gap is closed */ + uint64_t oldest; + struct glz_image *image = d->window->images[(d->window->tail_gap - 1) % d->window->nimages]; + + g_return_if_fail(image != NULL); + + oldest = image->hdr.id - image->hdr.win_head_dist; + glz_decoder_window_release(d->window, oldest); + } +} + +/* ------------------------------------------------------------------ */ + +static SpiceGlzDecoderOps glz_decoder_ops = { + .decode = decode, +}; + +void glz_decoder_window_clear(SpiceGlzDecoderWindow *w) +{ + int i; + + g_return_if_fail(w->nimages == 0 || w->images != NULL); + + for (i = 0; i < w->nimages; i++) { + if (w->images[i]) { + glz_image_destroy(w->images[i]); + } + } + + w->nimages = 16; + g_free(w->images); + w->images = g_new0(struct glz_image*, w->nimages); + w->tail_gap = 0; +} + +SpiceGlzDecoderWindow *glz_decoder_window_new(void) +{ + SpiceGlzDecoderWindow *w = g_new0(SpiceGlzDecoderWindow, 1); + glz_decoder_window_clear(w); + return w; +} + +void glz_decoder_window_destroy(SpiceGlzDecoderWindow *w) +{ + if (w == NULL) + return; + + glz_decoder_window_clear(w); + free(w->images); + free(w); +} + +SpiceGlzDecoder *glz_decoder_new(SpiceGlzDecoderWindow *w) +{ + GlibGlzDecoder *d = g_new0(GlibGlzDecoder, 1); + d->base.ops = &glz_decoder_ops; + d->window = w; + return &d->base; +} + +void glz_decoder_destroy(SpiceGlzDecoder *d) +{ + free(d); +} diff --git a/src/decode-jpeg.c b/src/decode-jpeg.c new file mode 100644 index 0000000..697d0de --- /dev/null +++ b/src/decode-jpeg.c @@ -0,0 +1,191 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "decode.h" + +#ifdef G_OS_WIN32 +/* We need some hacks to avoid warnings from the jpeg headers, ex: */ +/* #define HAVE_BOOLEAN */ +#define XMD_H +/* #undef FAR */ +/* but they are not compatible: uchar vs int........!@@(#$$??!@! */ +/* fix this with UGLY HACK! */ +/* #define boolean spice_jpeg_boolean */ +/* #define INT32 spice_jpeg_int32 */ +#endif + +#include +#include + +typedef struct GlibJpegDecoder +{ + SpiceJpegDecoder base; + struct jpeg_decompress_struct _cinfo; + struct jpeg_error_mgr _jerr; + struct jpeg_source_mgr _jsrc; + + uint8_t* _data; + int _data_size; + int _width; + int _height; +} GlibJpegDecoder; + +static void begin_decode(SpiceJpegDecoder *decoder, + uint8_t* data, int data_size, + int* out_width, int* out_height) +{ + GlibJpegDecoder *d = SPICE_CONTAINEROF(decoder, GlibJpegDecoder, base); + + g_return_if_fail(data != NULL); + g_return_if_fail(data_size != 0); + + if (d->_data) + jpeg_abort_decompress(&d->_cinfo); + + d->_data = data; + d->_data_size = data_size; + + d->_cinfo.src->next_input_byte = d->_data; + d->_cinfo.src->bytes_in_buffer = d->_data_size; + + jpeg_read_header(&d->_cinfo, TRUE); + + d->_cinfo.out_color_space = JCS_RGB; + d->_width = d->_cinfo.image_width; + d->_height = d->_cinfo.image_height; + + *out_width = d->_width; + *out_height = d->_height; +} + +/* TODO: move it elsewhere and reuse it in get_pixbuf(), optimize? */ +typedef void (*converter_rgb_t)(uint8_t* src, uint8_t* dest, int width); + +static void convert_rgb_to_bgr(uint8_t* src, uint8_t* dest, int width) +{ + int x; + + for (x = 0; x < width; x++) { + *dest++ = src[2]; + *dest++ = src[1]; + *dest++ = src[0]; + src += 3; + } +} + +static void convert_rgb_to_bgrx(uint8_t* src, uint8_t* dest, int width) +{ + int x; + + for (x = 0; x < width; x++) { + *dest++ = src[2]; + *dest++ = src[1]; + *dest++ = src[0]; + *dest++ = 0; + src += 3; + } +} + +static void decode(SpiceJpegDecoder *decoder, + uint8_t* dest, int stride, int format) +{ + GlibJpegDecoder *d = SPICE_CONTAINEROF(decoder, GlibJpegDecoder, base); + uint8_t* scan_line = g_alloca(d->_width * 3); + converter_rgb_t converter = NULL; + int row; + + switch (format) { + case SPICE_BITMAP_FMT_24BIT: + converter = convert_rgb_to_bgr; + break; + case SPICE_BITMAP_FMT_32BIT: + converter = convert_rgb_to_bgrx; + break; + default: + g_warning("bad bitmap format, %d", format); + return; + } + + g_return_if_fail(converter != NULL); + + jpeg_start_decompress(&d->_cinfo); + + for (row = 0; row < d->_height; row++) { + jpeg_read_scanlines(&d->_cinfo, &scan_line, 1); + converter(scan_line, dest, d->_width); + dest += stride; + } + + jpeg_finish_decompress(&d->_cinfo); +} + +static SpiceJpegDecoderOps jpeg_decoder_ops = { + .begin_decode = begin_decode, + .decode = decode, +}; + +static void jpeg_decoder_init_source(j_decompress_ptr cinfo) +{ +} + +static boolean jpeg_decoder_fill_input_buffer(j_decompress_ptr cinfo) +{ + g_warning("no more data for jpeg"); + return FALSE; +} + +static void jpeg_decoder_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + g_return_if_fail(num_bytes < (long)cinfo->src->bytes_in_buffer); + + cinfo->src->next_input_byte += num_bytes; + cinfo->src->bytes_in_buffer -= num_bytes; +} + +static void jpeg_decoder_term_source (j_decompress_ptr cinfo) +{ + return; +} + +SpiceJpegDecoder *jpeg_decoder_new(void) +{ + GlibJpegDecoder *d = g_new0(GlibJpegDecoder, 1); + + d->_cinfo.err = jpeg_std_error(&d->_jerr); + jpeg_create_decompress(&d->_cinfo); + + d->_cinfo.src = &d->_jsrc; + d->_cinfo.src->init_source = jpeg_decoder_init_source; + d->_cinfo.src->fill_input_buffer = jpeg_decoder_fill_input_buffer; + d->_cinfo.src->skip_input_data = jpeg_decoder_skip_input_data; + d->_cinfo.src->resync_to_restart = jpeg_resync_to_restart; + d->_cinfo.src->term_source = jpeg_decoder_term_source; + + d->base.ops = &jpeg_decoder_ops; + + return &d->base; +} + +void jpeg_decoder_destroy(SpiceJpegDecoder *decoder) +{ + GlibJpegDecoder *d = SPICE_CONTAINEROF(decoder, GlibJpegDecoder, base); + + jpeg_destroy_decompress(&d->_cinfo); + free(d); +} diff --git a/src/decode-zlib.c b/src/decode-zlib.c new file mode 100644 index 0000000..a5325c0 --- /dev/null +++ b/src/decode-zlib.c @@ -0,0 +1,89 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "decode.h" + +#ifndef __GNUC__ +#define ZLIB_WINAPI +#endif + +#include + +typedef struct GlibZlibDecoder +{ + SpiceZlibDecoder base; + z_stream _z_strm; +} GlibZlibDecoder; + +static void decode(SpiceZlibDecoder *decoder, + uint8_t *data, int data_size, + uint8_t *dest, int dest_size) +{ + GlibZlibDecoder *d = SPICE_CONTAINEROF(decoder, GlibZlibDecoder, base); + int z_ret; + + inflateReset(&d->_z_strm); + d->_z_strm.next_in = data; + d->_z_strm.avail_in = data_size; + d->_z_strm.next_out = dest; + d->_z_strm.avail_out = dest_size; + + z_ret = inflate(&d->_z_strm, Z_FINISH); + + if (z_ret != Z_STREAM_END) { + g_warning("zlib inflate failed, error %d", z_ret); + } +} + +static SpiceZlibDecoderOps zlib_decoder_ops = { + .decode = decode, +}; + +SpiceZlibDecoder *zlib_decoder_new(void) +{ + GlibZlibDecoder *d = g_new0(GlibZlibDecoder, 1); + int z_ret; + + d->_z_strm.zalloc = Z_NULL; + d->_z_strm.zfree = Z_NULL; + d->_z_strm.opaque = Z_NULL; + d->_z_strm.next_in = Z_NULL; + d->_z_strm.avail_in = 0; + z_ret = inflateInit(&d->_z_strm); + if (z_ret != Z_OK) { + g_warning("zlib decoder init failed, error %d", z_ret); + goto fail; + } + + d->base.ops = &zlib_decoder_ops; + + return &d->base; + +fail: + free(d); + return NULL; +} + +void zlib_decoder_destroy(SpiceZlibDecoder *decoder) +{ + GlibZlibDecoder *d = SPICE_CONTAINEROF(decoder, GlibZlibDecoder, base); + + inflateEnd(&d->_z_strm); + free(d); +} diff --git a/src/decode.h b/src/decode.h new file mode 100644 index 0000000..b274d67 --- /dev/null +++ b/src/decode.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICEGTK_DECODE_H_ +# define SPICEGTK_DECODE_H_ + +#include + +#include "client_sw_canvas.h" + +G_BEGIN_DECLS + +typedef struct SpiceGlzDecoderWindow SpiceGlzDecoderWindow; + +SpiceGlzDecoderWindow *glz_decoder_window_new(void); +void glz_decoder_window_clear(SpiceGlzDecoderWindow *w); +void glz_decoder_window_destroy(SpiceGlzDecoderWindow *w); + +SpiceGlzDecoder *glz_decoder_new(SpiceGlzDecoderWindow *w); +void glz_decoder_destroy(SpiceGlzDecoder *d); + +SpiceZlibDecoder *zlib_decoder_new(void); +void zlib_decoder_destroy(SpiceZlibDecoder *d); + +SpiceJpegDecoder *jpeg_decoder_new(void); +void jpeg_decoder_destroy(SpiceJpegDecoder *d); + +G_END_DECLS + +#endif // SPICEGTK_DECODE_H_ diff --git a/src/desktop-integration.c b/src/desktop-integration.c new file mode 100644 index 0000000..529fb05 --- /dev/null +++ b/src/desktop-integration.c @@ -0,0 +1,222 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "config.h" + +#include + +#include "spice-session-priv.h" +#include "desktop-integration.h" + +#include + +#define GNOME_SESSION_INHIBIT_AUTOMOUNT 16 + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_DESKTOP_INTEGRATION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationPrivate)) + +struct _SpiceDesktopIntegrationPrivate { +#if defined(USE_GDBUS) + GDBusProxy *gnome_session_proxy; +#else + GObject *gnome_session_proxy; /* dummy */ +#endif + guint gnome_automount_inhibit_cookie; +}; + +G_DEFINE_TYPE(SpiceDesktopIntegration, spice_desktop_integration, G_TYPE_OBJECT); + +/* ------------------------------------------------------------------ */ +/* Gnome specific code */ + +static void handle_dbus_call_error(const char *call, GError **_error) +{ + GError *error = *_error; + const char *message = error->message; + + g_warning("Error calling '%s': %s", call, message); + g_clear_error(_error); +} + +static gboolean gnome_integration_init(SpiceDesktopIntegration *self) +{ + G_GNUC_UNUSED SpiceDesktopIntegrationPrivate *priv = self->priv; + GError *error = NULL; + gboolean success = TRUE; + +#if defined(USE_GDBUS) + gchar *name_owner = NULL; + priv->gnome_session_proxy = + g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, + &error); + if (!error && + (name_owner = g_dbus_proxy_get_name_owner(priv->gnome_session_proxy)) == NULL) { + g_clear_object(&priv->gnome_session_proxy); + success = FALSE; + } + g_free(name_owner); +#else + success = FALSE; +#endif + + if (error) { + g_warning("Could not create org.gnome.SessionManager dbus proxy: %s", + error->message); + g_clear_error(&error); + return FALSE; + } + + return success; +} + +static void gnome_integration_inhibit_automount(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + GError *error = NULL; + G_GNUC_UNUSED const gchar *reason = + _("Automounting has been inhibited for USB auto-redirecting"); + + if (!priv->gnome_session_proxy) + return; + + g_return_if_fail(priv->gnome_automount_inhibit_cookie == 0); + +#if defined(USE_GDBUS) + GVariant *v = g_dbus_proxy_call_sync(priv->gnome_session_proxy, + "Inhibit", + g_variant_new("(susu)", + g_get_prgname(), + 0, + reason, + GNOME_SESSION_INHIBIT_AUTOMOUNT), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (v) + g_variant_get(v, "(u)", &priv->gnome_automount_inhibit_cookie); + + g_clear_pointer(&v, g_variant_unref); +#endif + if (error) + handle_dbus_call_error("org.gnome.SessionManager.Inhibit", &error); +} + +static void gnome_integration_uninhibit_automount(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + GError *error = NULL; + + if (!priv->gnome_session_proxy) + return; + + /* Cookie is 0 when we failed to inhibit (and when called from dispose) */ + if (priv->gnome_automount_inhibit_cookie == 0) + return; + +#if defined(USE_GDBUS) + GVariant *v = g_dbus_proxy_call_sync(priv->gnome_session_proxy, + "Uninhibit", + g_variant_new("(u)", + priv->gnome_automount_inhibit_cookie), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + g_clear_pointer(&v, g_variant_unref); +#endif + if (error) + handle_dbus_call_error("org.gnome.SessionManager.Uninhibit", &error); + + priv->gnome_automount_inhibit_cookie = 0; +} + +static void gnome_integration_dispose(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + + g_clear_object(&priv->gnome_session_proxy); +} + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +static void spice_desktop_integration_init(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv; + + priv = SPICE_DESKTOP_INTEGRATION_GET_PRIVATE(self); + self->priv = priv; + + if (!gnome_integration_init(self)) + g_warning("Warning no automount-inhibiting implementation available"); +} + +static void spice_desktop_integration_dispose(GObject *gobject) +{ + SpiceDesktopIntegration *self = SPICE_DESKTOP_INTEGRATION(gobject); + + gnome_integration_dispose(self); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_desktop_integration_parent_class)->dispose) + G_OBJECT_CLASS(spice_desktop_integration_parent_class)->dispose(gobject); +} + +static void spice_desktop_integration_class_init(SpiceDesktopIntegrationClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = spice_desktop_integration_dispose; + + g_type_class_add_private(klass, sizeof(SpiceDesktopIntegrationPrivate)); +} + +SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session) +{ + SpiceDesktopIntegration *self; + static GMutex mutex; + + g_return_val_if_fail(session != NULL, NULL); + + g_mutex_lock(&mutex); + self = g_object_get_data(G_OBJECT(session), "spice-desktop"); + if (self == NULL) { + self = g_object_new(SPICE_TYPE_DESKTOP_INTEGRATION, NULL); + g_object_set_data_full(G_OBJECT(session), "spice-desktop", self, g_object_unref); + } + g_mutex_unlock(&mutex); + + return self; +} + +void spice_desktop_integration_inhibit_automount(SpiceDesktopIntegration *self) +{ + gnome_integration_inhibit_automount(self); +} + +void spice_desktop_integration_uninhibit_automount(SpiceDesktopIntegration *self) +{ + gnome_integration_uninhibit_automount(self); +} diff --git a/src/desktop-integration.h b/src/desktop-integration.h new file mode 100644 index 0000000..3716089 --- /dev/null +++ b/src/desktop-integration.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_DESKTOP_INTEGRATION_H__ +#define __SPICE_DESKTOP_INTEGRATION_H__ + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_DESKTOP_INTEGRATION (spice_desktop_integration_get_type ()) +#define SPICE_DESKTOP_INTEGRATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegration)) +#define SPICE_DESKTOP_INTEGRATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationClass)) +#define SPICE_IS_DESKTOP_INTEGRATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_DESKTOP_INTEGRATION)) +#define SPICE_IS_DESKTOP_INTEGRATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_DESKTOP_INTEGRATION)) +#define SPICE_DESKTOP_INTEGRATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationClass)) + +typedef struct _SpiceDesktopIntegration SpiceDesktopIntegration; +typedef struct _SpiceDesktopIntegrationClass SpiceDesktopIntegrationClass; +typedef struct _SpiceDesktopIntegrationPrivate SpiceDesktopIntegrationPrivate; + +/* + * SpiceDesktopIntegration offers helper-functions to do desktop environment + * and/or platform specific tasks like disabling automount, disabling the + * screen-saver, etc. SpiceDesktopIntegration is for internal spice-gtk usage + * only! + */ +struct _SpiceDesktopIntegration +{ + GObject parent; + + SpiceDesktopIntegrationPrivate *priv; +}; + +struct _SpiceDesktopIntegrationClass +{ + GObjectClass parent_class; +}; + +GType spice_desktop_integration_get_type(void); +SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session); +void spice_desktop_integration_inhibit_automount(SpiceDesktopIntegration *self); +void spice_desktop_integration_uninhibit_automount(SpiceDesktopIntegration *self); + +G_END_DECLS + +#endif /* __SPICE_DESKTOP_INTEGRATION_H__ */ diff --git a/src/gio-coroutine.c b/src/gio-coroutine.c new file mode 100644 index 0000000..c866e15 --- /dev/null +++ b/src/gio-coroutine.c @@ -0,0 +1,275 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2006 Anthony Liguori + Copyright (C) 2009-2010 Daniel P. Berrange + + 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.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "config.h" + +#include "gio-coroutine.h" + +typedef struct _GConditionWaitSource +{ + GCoroutine *self; + GSource src; + GConditionWaitFunc func; + gpointer data; +} GConditionWaitSource; + +GCoroutine* g_coroutine_self(void) +{ + return (GCoroutine*)coroutine_self(); +} + +/* Main loop helper functions */ +static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED, + GIOCondition cond, + gpointer data) +{ + struct coroutine *to = data; + coroutine_yieldto(to, &cond); + return FALSE; +} + +GIOCondition g_coroutine_socket_wait(GCoroutine *self, + GSocket *sock, + GIOCondition cond) +{ + GIOCondition *ret, val = 0; + GSource *src; + + g_return_val_if_fail(self != NULL, 0); + g_return_val_if_fail(self->wait_id == 0, 0); + g_return_val_if_fail(sock != NULL, 0); + + src = g_socket_create_source(sock, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, NULL); + g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, self, NULL); + self->wait_id = g_source_attach(src, NULL); + ret = coroutine_yield(NULL); + g_source_unref(src); + + if (ret != NULL) + val = *ret; + else + g_source_remove(self->wait_id); + + self->wait_id = 0; + return val; +} + +void g_coroutine_condition_cancel(GCoroutine *coroutine) +{ + g_return_if_fail(coroutine != NULL); + + if (coroutine->condition_id == 0) + return; + + g_source_remove(coroutine->condition_id); + coroutine->condition_id = 0; +} + +void g_coroutine_wakeup(GCoroutine *coroutine) +{ + g_return_if_fail(coroutine != NULL); + g_return_if_fail(coroutine != g_coroutine_self()); + + if (coroutine->wait_id) + coroutine_yieldto(&coroutine->coroutine, NULL); +} + +/* + * Call immediately before the main loop does an iteration. Returns + * true if the condition we're checking is ready for dispatch + */ +static gboolean g_condition_wait_prepare(GSource *src, + int *timeout) { + GConditionWaitSource *vsrc = (GConditionWaitSource *)src; + *timeout = -1; + return vsrc->func(vsrc->data); +} + +/* + * Call immediately after the main loop does an iteration. Returns + * true if the condition we're checking is ready for dispatch + */ +static gboolean g_condition_wait_check(GSource *src) +{ + GConditionWaitSource *vsrc = (GConditionWaitSource *)src; + return vsrc->func(vsrc->data); +} + +static gboolean g_condition_wait_dispatch(GSource *src G_GNUC_UNUSED, + GSourceFunc cb, + gpointer data) { + return cb(data); +} + +GSourceFuncs waitFuncs = { + .prepare = g_condition_wait_prepare, + .check = g_condition_wait_check, + .dispatch = g_condition_wait_dispatch, +}; + +static gboolean g_condition_wait_helper(gpointer data) +{ + GCoroutine *self = (GCoroutine *)data; + coroutine_yieldto(&self->coroutine, NULL); + return FALSE; +} + +/* + * g_coroutine_condition_wait: + * @coroutine: the coroutine to wait on + * @func: the condition callback + * @data: the user data passed to @func callback + * + * This function will wait on caller coroutine until @func returns %TRUE. + * + * @func is called when entering the main loop from the main context (coroutine). + * + * The condition can be cancelled by calling g_coroutine_wakeup() + * + * Returns: %TRUE if condition reached, %FALSE if not and cancelled + */ +gboolean g_coroutine_condition_wait(GCoroutine *self, GConditionWaitFunc func, gpointer data) +{ + GSource *src; + GConditionWaitSource *vsrc; + + g_return_val_if_fail(self != NULL, FALSE); + g_return_val_if_fail(self->condition_id == 0, FALSE); + g_return_val_if_fail(func != NULL, FALSE); + + /* Short-circuit check in case we've got it ahead of time */ + if (func(data)) + return TRUE; + + /* + * Don't have it, so yield to the main loop, checking the condition + * on each iteration of the main loop + */ + src = g_source_new(&waitFuncs, sizeof(GConditionWaitSource)); + vsrc = (GConditionWaitSource *)src; + + vsrc->func = func; + vsrc->data = data; + vsrc->self = self; + + self->condition_id = g_source_attach(src, NULL); + g_source_set_callback(src, g_condition_wait_helper, self, NULL); + coroutine_yield(NULL); + g_source_unref(src); + + /* it got woked up / cancelled? */ + if (self->condition_id == 0) + return func(data); + + self->condition_id = 0; + return TRUE; +} + +struct signal_data +{ + gpointer instance; + struct coroutine *caller; + guint signal_id; + GQuark detail; + const gchar *propname; + gboolean notified; + va_list var_args; +}; + +static gboolean emit_main_context(gpointer opaque) +{ + struct signal_data *signal = opaque; + + g_signal_emit_valist(signal->instance, signal->signal_id, + signal->detail, signal->var_args); + signal->notified = TRUE; + + coroutine_yieldto(signal->caller, NULL); + + return FALSE; +} + +void +g_coroutine_signal_emit(gpointer instance, guint signal_id, + GQuark detail, ...) +{ + struct signal_data data = { + .instance = instance, + .signal_id = signal_id, + .detail = detail, + .caller = coroutine_self(), + }; + + va_start (data.var_args, detail); + + if (coroutine_self_is_main()) { + g_signal_emit_valist(instance, signal_id, detail, data.var_args); + } else { + g_object_ref(instance); + g_idle_add(emit_main_context, &data); + coroutine_yield(NULL); + g_warn_if_fail(data.notified); + g_object_unref(instance); + } + + va_end (data.var_args); +} + + +static gboolean notify_main_context(gpointer opaque) +{ + struct signal_data *signal = opaque; + + g_object_notify(signal->instance, signal->propname); + signal->notified = TRUE; + + coroutine_yieldto(signal->caller, NULL); + + return FALSE; +} + +/* coroutine -> main context */ +void g_coroutine_object_notify(GObject *object, + const gchar *property_name) +{ + struct signal_data data; + + if (coroutine_self_is_main()) { + g_object_notify(object, property_name); + } else { + + data.instance = g_object_ref(object); + data.caller = coroutine_self(); + data.propname = (gpointer)property_name; + data.notified = FALSE; + + g_idle_add(notify_main_context, &data); + + /* This switches to the system coroutine context, lets + * the idle function run to dispatch the signal, and + * finally returns once complete. ie this is synchronous + * from the POV of the coroutine despite there being + * an idle function involved + */ + coroutine_yield(NULL); + g_warn_if_fail(data.notified); + g_object_unref(object); + } +} diff --git a/src/gio-coroutine.h b/src/gio-coroutine.h new file mode 100644 index 0000000..b3a6d78 --- /dev/null +++ b/src/gio-coroutine.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2006 Anthony Liguori + Copyright (C) 2009-2010 Daniel P. Berrange + + 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.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef __GIO_COROUTINE_H__ +#define __GIO_COROUTINE_H__ + +#include +#include "coroutine.h" + +G_BEGIN_DECLS + +typedef struct _GCoroutine GCoroutine; + +struct _GCoroutine +{ + struct coroutine coroutine; + guint wait_id; + guint condition_id; +}; + +/* + * A special GSource impl which allows us to wait on a certain + * condition to be satisfied. This is effectively a boolean test + * run on each iteration of the main loop. So whenever a file has + * new I/O, or a timer occurs, etc we'll do the check. This is + * pretty efficient compared to a normal GLib Idle func which has + * to busy wait on a timeout, since our condition is only checked + * when some other source's state changes + */ +typedef gboolean (*GConditionWaitFunc)(gpointer); + +typedef void (*GSignalEmitMainFunc)(GObject *object, int signum, gpointer params); + +GCoroutine* g_coroutine_self (void); +void g_coroutine_wakeup (GCoroutine *coroutine); +GIOCondition g_coroutine_socket_wait (GCoroutine *coroutine, + GSocket *sock, GIOCondition cond); +gboolean g_coroutine_condition_wait (GCoroutine *coroutine, + GConditionWaitFunc func, gpointer data); +void g_coroutine_condition_cancel(GCoroutine *coroutine); + +void g_coroutine_signal_emit (gpointer instance, guint signal_id, + GQuark detail, ...); + +void g_coroutine_object_notify(GObject *object, const gchar *property_name); + +G_END_DECLS + +#endif /* __GIO_COROUTINE_H__ */ diff --git a/src/giopipe.c b/src/giopipe.c new file mode 100644 index 0000000..e76090c --- /dev/null +++ b/src/giopipe.c @@ -0,0 +1,488 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include +#include + +#include "giopipe.h" + +#define TYPE_PIPE_INPUT_STREAM (pipe_input_stream_get_type ()) +#define PIPE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_PIPE_INPUT_STREAM, PipeInputStream)) +#define PIPE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TYPE_PIPE_INPUT_STREAM, PipeInputStreamClass)) +#define IS_PIPE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_PIPE_INPUT_STREAM)) +#define IS_PIPE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_PIPE_INPUT_STREAM)) +#define PIPE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_PIPE_INPUT_STREAM, PipeInputStreamClass)) + +typedef struct _PipeInputStreamClass PipeInputStreamClass; +typedef struct _PipeInputStream PipeInputStream; +typedef struct _PipeOutputStream PipeOutputStream; + +struct _PipeInputStream +{ + GInputStream parent_instance; + + PipeOutputStream *peer; + gssize read; + + /* GIOstream:closed is protected against pending operations, so we + * use an additional close flag to cancel those when the peer is + * closing. + */ + gboolean peer_closed; + GList *sources; +}; + +struct _PipeInputStreamClass +{ + GInputStreamClass parent_class; +}; + +#define TYPE_PIPE_OUTPUT_STREAM (pipe_output_stream_get_type ()) +#define PIPE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_PIPE_OUTPUT_STREAM, PipeOutputStream)) +#define PIPE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TYPE_PIPE_OUTPUT_STREAM, PipeOutputStreamClass)) +#define IS_PIPE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_PIPE_OUTPUT_STREAM)) +#define IS_PIPE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_PIPE_OUTPUT_STREAM)) +#define PIPE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_PIPE_OUTPUT_STREAM, PipeOutputStreamClass)) + +typedef struct _PipeOutputStreamClass PipeOutputStreamClass; + +struct _PipeOutputStream +{ + GOutputStream parent_instance; + + PipeInputStream *peer; + const gchar *buffer; + gsize count; + gboolean peer_closed; + GList *sources; +}; + +struct _PipeOutputStreamClass +{ + GOutputStreamClass parent_class; +}; + +static void pipe_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface); +static void pipe_input_stream_check_source (PipeInputStream *self); +static void pipe_output_stream_check_source (PipeOutputStream *self); + +static GType pipe_input_stream_get_type(void); + +G_DEFINE_TYPE_WITH_CODE (PipeInputStream, pipe_input_stream, G_TYPE_INPUT_STREAM, + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + pipe_input_stream_pollable_iface_init)) + +static gssize +pipe_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + PipeInputStream *self = PIPE_INPUT_STREAM (stream); + + g_return_val_if_fail(count > 0, -1); + + if (g_input_stream_is_closed (stream) || self->peer_closed) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, + "Stream is already closed"); + return -1; + } + + if (!self->peer->buffer) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + g_strerror(EAGAIN)); + return -1; + } + + count = MIN(self->peer->count, count); + memcpy(buffer, self->peer->buffer, count); + self->read = count; + self->peer->buffer = NULL; + + //g_debug("read %p :%"G_GSIZE_FORMAT, self->peer, count); + /* schedule peer source */ + pipe_output_stream_check_source(self->peer); + + return count; +} + +static GList * +set_all_sources_ready (GList *sources) +{ + GList *it = sources; + while (it != NULL) { + GSource *s = it->data; + GList *next = it->next; + + if (s == NULL || g_source_is_destroyed(s)) { + /* remove */ + sources = g_list_delete_link(sources, it); + g_source_unref(s); + } else { + /* dispatch */ + g_source_set_ready_time(s, 0); + } + it = next; + } + return sources; +} + +static void +pipe_input_stream_check_source (PipeInputStream *self) +{ + if (g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); +} + +static gboolean +pipe_input_stream_close (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + PipeInputStream *self; + + self = PIPE_INPUT_STREAM(stream); + + if (self->peer) { + /* ignore any pending errors */ + self->peer->peer_closed = TRUE; + g_output_stream_close(G_OUTPUT_STREAM(self->peer), cancellable, NULL); + pipe_output_stream_check_source(self->peer); + } + + return TRUE; +} + +static void +pipe_input_stream_close_async (GInputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GTask *task; + + task = g_task_new (stream, cancellable, callback, data); + + /* will always return TRUE */ + pipe_input_stream_close (stream, cancellable, NULL); + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static gboolean +pipe_input_stream_close_finish (GInputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void +pipe_input_stream_init (PipeInputStream *self) +{ + self->read = -1; +} + +static void +pipe_input_stream_dispose(GObject *object) +{ + PipeInputStream *self; + + self = PIPE_INPUT_STREAM(object); + + if (self->peer) { + g_object_remove_weak_pointer(G_OBJECT(self->peer), (gpointer*)&self->peer); + self->peer = NULL; + } + + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; + + G_OBJECT_CLASS(pipe_input_stream_parent_class)->dispose (object); +} + +static void +pipe_input_stream_class_init (PipeInputStreamClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass); + + istream_class->read_fn = pipe_input_stream_read; + istream_class->close_fn = pipe_input_stream_close; + istream_class->close_async = pipe_input_stream_close_async; + istream_class->close_finish = pipe_input_stream_close_finish; + + gobject_class->dispose = pipe_input_stream_dispose; +} + +static gboolean +pipe_input_stream_is_readable (GPollableInputStream *stream) +{ + PipeInputStream *self = PIPE_INPUT_STREAM (stream); + gboolean readable; + + readable = (self->peer && self->peer->buffer && self->read == -1) || self->peer_closed; + //g_debug("readable %p %d", self->peer, readable); + + return readable; +} + +static GSource * +pipe_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + PipeInputStream *self = PIPE_INPUT_STREAM(stream); + GSource *pollable_source; + + pollable_source = g_pollable_source_new_full (self, NULL, cancellable); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); + + return pollable_source; +} + +static void +pipe_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface) +{ + iface->is_readable = pipe_input_stream_is_readable; + iface->create_source = pipe_input_stream_create_source; +} + +static void pipe_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface); + +static GType pipe_output_stream_get_type(void); + +G_DEFINE_TYPE_WITH_CODE (PipeOutputStream, pipe_output_stream, G_TYPE_OUTPUT_STREAM, + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, + pipe_output_stream_pollable_iface_init)) + +static gssize +pipe_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + PipeOutputStream *self = PIPE_OUTPUT_STREAM(stream); + PipeInputStream *peer = self->peer; + + //g_debug("write %p :%"G_GSIZE_FORMAT, stream, count); + if (g_output_stream_is_closed (stream) || self->peer_closed) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, + "Stream is already closed"); + return -1; + } + + /* this abuses pollable stream, writing sync would likely lead to + crashes, since the buffer pointer would become invalid, a + generic solution would need a copy.. + */ + g_return_val_if_fail(self->buffer == buffer || self->buffer == NULL, -1); + self->buffer = buffer; + self->count = count; + + pipe_input_stream_check_source(self->peer); + + if (peer->read < 0) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + g_strerror (EAGAIN)); + return -1; + } + + g_assert(peer->read <= self->count); + count = peer->read; + + self->buffer = NULL; + self->count = 0; + peer->read = -1; + + return count; +} + +static void +pipe_output_stream_init (PipeOutputStream *stream) +{ +} + +static void +pipe_output_stream_dispose(GObject *object) +{ + PipeOutputStream *self; + + self = PIPE_OUTPUT_STREAM(object); + + if (self->peer) { + g_object_remove_weak_pointer(G_OBJECT(self->peer), (gpointer*)&self->peer); + self->peer = NULL; + } + + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; + + G_OBJECT_CLASS(pipe_output_stream_parent_class)->dispose (object); +} + +static void +pipe_output_stream_check_source (PipeOutputStream *self) +{ + if (g_pollable_output_stream_is_writable(G_POLLABLE_OUTPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); +} + +static gboolean +pipe_output_stream_close (GOutputStream *stream, + GCancellable *cancellable, + GError **error) +{ + PipeOutputStream *self; + + self = PIPE_OUTPUT_STREAM(stream); + + if (self->peer) { + /* ignore any pending errors */ + self->peer->peer_closed = TRUE; + g_input_stream_close(G_INPUT_STREAM(self->peer), cancellable, NULL); + pipe_input_stream_check_source(self->peer); + } + + return TRUE; +} + +static void +pipe_output_stream_close_async (GOutputStream *stream, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GTask *task; + + task = g_task_new (stream, cancellable, callback, data); + + /* will always return TRUE */ + pipe_output_stream_close (stream, cancellable, NULL); + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static gboolean +pipe_output_stream_close_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + + +static void +pipe_output_stream_class_init (PipeOutputStreamClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GOutputStreamClass *ostream_class = G_OUTPUT_STREAM_CLASS (klass); + + ostream_class->write_fn = pipe_output_stream_write; + ostream_class->close_fn = pipe_output_stream_close; + ostream_class->close_async = pipe_output_stream_close_async; + ostream_class->close_finish = pipe_output_stream_close_finish; + + gobject_class->dispose = pipe_output_stream_dispose; +} + +static gboolean +pipe_output_stream_is_writable (GPollableOutputStream *stream) +{ + PipeOutputStream *self = PIPE_OUTPUT_STREAM(stream); + gboolean writable; + + writable = self->buffer == NULL || self->peer->read >= 0; + //g_debug("writable %p %d", self, writable); + + return writable; +} + +static GSource * +pipe_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + PipeOutputStream *self = PIPE_OUTPUT_STREAM(stream); + GSource *pollable_source; + + pollable_source = g_pollable_source_new_full (self, NULL, cancellable); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); + + return pollable_source; +} + +static void +pipe_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface) +{ + iface->is_writable = pipe_output_stream_is_writable; + iface->create_source = pipe_output_stream_create_source; +} + +static void +make_gio_pipe(GInputStream **input, GOutputStream **output) +{ + PipeInputStream *in; + PipeOutputStream *out; + + g_return_if_fail(input != NULL && *input == NULL); + g_return_if_fail(output != NULL && *output == NULL); + + in = g_object_new(TYPE_PIPE_INPUT_STREAM, NULL); + out = g_object_new(TYPE_PIPE_OUTPUT_STREAM, NULL); + + out->peer = in; + g_object_add_weak_pointer(G_OBJECT(in), (gpointer*)&out->peer); + + in->peer = out; + g_object_add_weak_pointer(G_OBJECT(out), (gpointer*)&in->peer); + + *input = G_INPUT_STREAM(in); + *output = G_OUTPUT_STREAM(out); +} + +G_GNUC_INTERNAL void +spice_make_pipe(GIOStream **p1, GIOStream **p2) +{ + GInputStream *in1 = NULL, *in2 = NULL; + GOutputStream *out1 = NULL, *out2 = NULL; + + g_return_if_fail(p1 != NULL); + g_return_if_fail(p2 != NULL); + g_return_if_fail(*p1 == NULL); + g_return_if_fail(*p2 == NULL); + + make_gio_pipe(&in1, &out2); + make_gio_pipe(&in2, &out1); + + *p1 = g_simple_io_stream_new(in1, out1); + *p2 = g_simple_io_stream_new(in2, out2); + + g_object_unref(in1); + g_object_unref(in2); + g_object_unref(out1); + g_object_unref(out2); +} diff --git a/src/giopipe.h b/src/giopipe.h new file mode 100644 index 0000000..46c2c9c --- /dev/null +++ b/src/giopipe.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_GIO_PIPE_H__ +#define __SPICE_GIO_PIPE_H__ + +#include + +G_BEGIN_DECLS + +void spice_make_pipe(GIOStream **p1, GIOStream **p2); + +G_END_DECLS + +#endif /* __SPICE_GIO_PIPE_H__ */ diff --git a/src/keymap-gen.pl b/src/keymap-gen.pl new file mode 100755 index 0000000..56953f8 --- /dev/null +++ b/src/keymap-gen.pl @@ -0,0 +1,214 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Text::CSV; + +my %names = ( + linux => [], + osx => [] +); + +my %namecolumns = ( + linux => 0, + osx => 2, + win32 => 10, + x11 => 14, + ); + +# Base data sources: +# +# linux: Linux: linux/input.h (master set) +# osx: OS-X: Carbon/HIToolbox/Events.h (manually mapped) +# atset1: AT Set 1: linux/drivers/input/keyboard/atkbd.c (atkbd_set2_keycode + atkbd_unxlate_table) +# atset2: AT Set 2: linux/drivers/input/keyboard/atkbd.c (atkbd_set2_keycode) +# atset3: AT Set 3: linux/drivers/input/keyboard/atkbd.c (atkbd_set3_keycode) +# xt: XT: linux/drivers/input/keyboard/xt.c (xtkbd_keycode) +# xtkbd: Linux RAW: linux/drivers/char/keyboard.c (x86_keycodes) +# usb: USB HID: linux/drivers/hid/usbhid/usbkbd.c (usb_kbd_keycode) +# win32: Win32: mingw32/winuser.h (manually mapped) +# xwinxt: XWin XT: xorg-server/hw/xwin/{winkeybd.c,winkeynames.h} (xt + manually transcribed) +# xkbdxt: XKBD XT: xf86-input-keyboard/src/at_scancode.c +#(xt + manually transcribed) +# x11: X11 keysyms: http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h +# +# Derived data sources +# +# xorgevdev: Xorg + evdev: linux + an offset +# xorgkbd: Xorg + kbd: xkbdxt + an offset +# xorgxquartz: Xorg + OS-X: osx + an offset +# xorgxwin: Xorg + Cygwin: xwinxt + an offset +# rfb: XT over RFB: xtkbd + special re-encoding of high bit + +my @basemaps = qw(linux osx atset1 atset2 atset3 xt xtkbd usb win32 xwinxt xkbdxt x11); +my @derivedmaps = qw(xorgevdev xorgkbd xorgxquartz xorgxwin rfb); +my @maps = (@basemaps, @derivedmaps); + +my %maps; + +foreach my $map (@maps) { + $maps{$map} = [ [], [] ]; +} +my %mapcolumns = ( + osx => 3, + atset1 => 4, + atset2 => 5, + atset3 => 6, + xt => 7, + xtkbd => 8, + usb => 9, + win32 => 11, + xwinxt => 12, + xkbdxt => 13, + x11 => 15 + ); + +sub help { + my $msg = shift; + print $msg; + print "\n"; + print "Valid keymaps are:\n"; + print "\n"; + foreach my $name (sort { $a cmp $b } keys %maps) { + print " $name\n"; + } + print "\n"; + exit (1); +} + +if ($#ARGV != 2) { + help("syntax: $0 KEYMAPS SRCMAP DSTMAP\n"); +} + +my $keymaps = shift @ARGV; +my $src = shift @ARGV; +my $dst = shift @ARGV; + +help("$src is not a known keymap\n") unless exists $maps{$src}; +help("$dst is not a known keymap\n") unless exists $maps{$dst}; + + +open CSV, $keymaps + or die "cannot read $keymaps: $!"; + +my $csv = Text::CSV->new(); +# Discard column headings +$csv->getline(\*CSV); + +my $row; +while ($row = $csv->getline(\*CSV)) { + my $linux = $row->[1]; + + $linux = hex($linux) if $linux =~ /0x/; + + my $to = $maps{linux}->[0]; + my $from = $maps{linux}->[1]; + $to->[$linux] = $linux; + $from->[$linux] = $linux; + + foreach my $name (keys %namecolumns) { + my $col = $namecolumns{$name}; + my $val = $row->[$col]; + + $val = "" unless defined $val; + + $names{$name}->[$linux] = $val; + } + + foreach my $name (keys %mapcolumns) { + my $col = $mapcolumns{$name}; + my $val = $row->[$col]; + + next unless defined $val && $val ne ""; + $val = hex($val) if $val =~ /0x/; + + $to = $maps{$name}->[0]; + $from = $maps{$name}->[1]; + $to->[$linux] = $val; + $from->[$val] = $linux; + } + + # XXX there are some special cases in kbd to handle + # Xorg KBD driver is the Xorg KBD XT codes offset by +8 + # The XKBD XT codes are the same as normal XT codes + # for values <= 83, and completely made up for extended + # scancodes :-( + ($to, $from) = @{$maps{xorgkbd}}; + if (defined $maps{xkbdxt}->[0]->[$linux]) { + $to->[$linux] = $maps{xkbdxt}->[0]->[$linux] + 8; + $from->[$to->[$linux]] = $linux; + } + + # Xorg evdev is simply Linux keycodes offset by +8 + ($to, $from) = @{$maps{xorgevdev}}; + $to->[$linux] = $linux + 8; + $from->[$to->[$linux]] = $linux; + + # Xorg XQuartz is simply OS-X keycodes offset by +8 + ($to, $from) = @{$maps{xorgxquartz}}; + if (defined $maps{osx}->[0]->[$linux]) { + $to->[$linux] = $maps{osx}->[0]->[$linux] + 8; + $from->[$to->[$linux]] = $linux; + } + + # RFB keycodes are XT kbd keycodes with a slightly + # different encoding of 0xe0 scan codes. RFB uses + # the high bit of the first byte, instead of the low + # bit of the second byte. + ($to, $from) = @{$maps{rfb}}; + my $xtkbd = $maps{xtkbd}->[0]->[$linux]; + if (defined $xtkbd) { + $to->[$linux] = $xtkbd ? (($xtkbd & 0x100)>>1) | ($xtkbd & 0x7f) : 0; + $from->[$to->[$linux]] = $linux; + } + + # Xorg Cygwin is the Xorg Cygwin XT codes offset by +8 + # The Cygwin XT codes are the same as normal XT codes + # for values <= 83, and completely made up for extended + # scancodes :-( + ($to, $from) = @{$maps{xorgxwin}}; + if (defined $maps{xwinxt}->[0]->[$linux]) { + $to->[$linux] = $maps{xwinxt}->[0]->[$linux] + 8; + $from->[$to->[$linux]] = $linux; + } + +# print $linux, "\n"; +} + +close CSV; + +my $srcmap = $maps{$src}->[1]; +my $dstmap = $maps{$dst}->[0]; + +printf "static const guint16 keymap_%s2%s[] = {\n", $src, $dst; + +for (my $i = 0 ; $i <= $#{$srcmap} ; $i++) { + my $linux = $srcmap->[$i] || 0; + my $j = $dstmap->[$linux]; + next unless $linux && $j; + + my $srcname = $names{$src}->[$linux] if exists $names{$src}; + my $dstname = $names{$dst}->[$linux] if exists $names{$dst}; + my $vianame = $names{linux}->[$linux] unless $src eq "linux" || $dst eq "linux"; + + $srcname = "" unless $srcname; + $dstname = "" unless $dstname; + $vianame = "" unless $vianame; + $srcname = " ($srcname)" if $srcname; + $dstname = " ($dstname)" if $dstname; + $vianame = " ($vianame)" if $vianame; + + my $comment; + if ($src ne "linux" && $dst ne "linux") { + $comment = sprintf "%d%s => %d%s via %d%s", $i, $srcname, $j, $dstname, $linux, $vianame; + } else { + $comment = sprintf "%d%s => %d%s", $i, $srcname, $j, $dstname; + } + + my $data = sprintf "[0x%x] = 0x%x,", $i, $j; + + printf " %-20s /* %s */\n", $data, $comment; +} + +print "};\n"; diff --git a/src/keymaps.csv b/src/keymaps.csv new file mode 100644 index 0000000..9052e3b --- /dev/null +++ b/src/keymaps.csv @@ -0,0 +1,490 @@ +"Linux Name","Linux Keycode","OS-X Name","OS-X Keycode","AT set1 keycode","AT set2 keycode","AT set3 keycode",XT,"XT KBD","USB Keycodes","Win32 Name","Win32 Keycode","Xwin XT","Xfree86 KBD XT","X11 keysym","X11 keycode" +KEY_RESERVED,0,,,,,,,,,,,,,, +KEY_ESC,1,Escape,0x35,1,118,8,1,1,41,VK_ESCAPE,0x1b,1,1,XK_Escape,0xff1b +KEY_1,2,ANSI_1,0x12,2,22,22,2,2,30,VK_1,0x31,2,2,XK_1,0x0031 +KEY_2,3,ANSI_2,0x13,3,30,30,3,3,31,VK_2,0x32,3,3,XK_2,0x0032 +KEY_3,4,ANSI_3,0x14,4,38,38,4,4,32,VK_3,0x33,4,4,XK_3,0x0033 +KEY_4,5,ANSI_4,0x15,5,37,37,5,5,33,VK_4,0x34,5,5,XK_4,0x0034 +KEY_5,6,ANSI_5,0x17,6,46,46,6,6,34,VK_5,0x35,6,6,XK_5,0x0035 +KEY_6,7,ANSI_6,0x16,7,54,54,7,7,35,VK_6,0x36,7,7,XK_6,0x0036 +KEY_7,8,ANSI_7,0x1a,8,61,61,8,8,36,VK_7,0x37,8,8,XK_7,0x0037 +KEY_8,9,ANSI_8,0x1c,9,62,62,9,9,37,VK_8,0x38,9,9,XK_8,0x0038 +KEY_9,10,ANSI_9,0x19,10,70,70,10,10,38,VK_9,0x39,10,10,XK_9,0x0039 +KEY_0,11,ANSI_0,0x1d,11,69,69,11,11,39,VK_0,0x30,11,11,XK_0,0x0030 +KEY_MINUS,12,ANSI_Minus,0x1b,12,78,78,12,12,45,VK_OEM_MINUS,0xbd,12,12,XK_minus,0x002d +KEY_EQUAL,13,ANSI_Equal,0x18,13,85,85,13,13,46,VK_OEM_PLUS,0xbb,13,13,XK_equal,0x003d +KEY_BACKSPACE,14,Delete,0x33,14,102,102,14,14,42,VK_BACK,0x08,14,14,XK_BackSpace,0xff08 +KEY_TAB,15,Tab,0x30,15,13,13,15,15,43,VK_TAB,0x09,15,15,XK_Tab,0xff09 +KEY_Q,16,ANSI_Q,0xc,16,21,21,16,16,20,VK_Q,0x51,16,16,XK_Q,0x0051 +KEY_Q,16,ANSI_Q,0xc,16,21,21,16,16,20,VK_Q,0x51,16,16,XK_q,0x0071 +KEY_W,17,ANSI_W,0xd,17,29,29,17,17,26,VK_W,0x57,17,17,XK_W,0x0057 +KEY_W,17,ANSI_W,0xd,17,29,29,17,17,26,VK_W,0x57,17,17,XK_w,0x0077 +KEY_E,18,ANSI_E,0xe,18,36,36,18,18,8,VK_E,0x45,18,18,XK_E,0x0045 +KEY_E,18,ANSI_E,0xe,18,36,36,18,18,8,VK_E,0x45,18,18,XK_e,0x0065 +KEY_R,19,ANSI_R,0xf,19,45,45,19,19,21,VK_R,0x52,19,19,XK_R,0x0052 +KEY_R,19,ANSI_R,0xf,19,45,45,19,19,21,VK_R,0x52,19,19,XK_r,0x0072 +KEY_T,20,ANSI_T,0x11,20,44,44,20,20,23,VK_T,0x54,20,20,XK_T,0x0054 +KEY_T,20,ANSI_T,0x11,20,44,44,20,20,23,VK_T,0x54,20,20,XK_t,0x0074 +KEY_Y,21,ANSI_Y,0x10,21,53,53,21,21,28,VK_Y,0x59,21,21,XK_Y,0x0059 +KEY_Y,21,ANSI_Y,0x10,21,53,53,21,21,28,VK_Y,0x59,21,21,XK_y,0x0079 +KEY_U,22,ANSI_U,0x20,22,60,60,22,22,24,VK_U,0x55,22,22,XK_U,0x0055 +KEY_U,22,ANSI_U,0x20,22,60,60,22,22,24,VK_U,0x55,22,22,XK_u,0x0075 +KEY_I,23,ANSI_I,0x22,23,67,67,23,23,12,VK_I,0x49,23,23,XK_I,0x0049 +KEY_I,23,ANSI_I,0x22,23,67,67,23,23,12,VK_I,0x49,23,23,XK_i,0x0069 +KEY_O,24,ANSI_O,0x1f,24,68,68,24,24,18,VK_O,0x4f,24,24,XK_O,0x004f +KEY_O,24,ANSI_O,0x1f,24,68,68,24,24,18,VK_O,0x4f,24,24,XK_o,0x006f +KEY_P,25,ANSI_P,0x23,25,77,77,25,25,19,VK_P,0x50,25,25,XK_P,0x0050 +KEY_P,25,ANSI_P,0x23,25,77,77,25,25,19,VK_P,0x50,25,25,XK_p,0x0070 +KEY_LEFTBRACE,26,ANSI_LeftBracket,0x21,26,84,84,26,26,47,VK_OEM_4,0xdb,26,26,XK_bracketleft,0x005b +KEY_RIGHTBRACE,27,ANSI_RightBracket,0x1e,27,91,91,27,27,48,VK_OEM_6,0xdd,27,27,XK_bracketright,0x005d +KEY_ENTER,28,Return,0x24,28,90,90,28,28,40,VK_RETURN,0x0d,28,28,XK_Return,0xff0d +KEY_LEFTCTRL,29,Control,0x3b,29,20,17,29,29,224,VK_LCONTROL,0xa2,29,29,XK_Control_L,0xffe3 +KEY_LEFTCTRL,29,Control,0x3b,29,20,17,29,29,224,VK_CONTROL,0x11,29,29,XK_Control_L,0xffe3 +KEY_A,30,ANSI_A,0x0,30,28,28,30,30,4,VK_A,0x41,30,30,XK_A,0x0041 +KEY_A,30,ANSI_A,0x0,30,28,28,30,30,4,VK_A,0x41,30,30,XK_a,0x0061 +KEY_S,31,ANSI_S,0x1,31,27,27,31,31,22,VK_S,0x53,31,31,XK_S,0x0053 +KEY_S,31,ANSI_S,0x1,31,27,27,31,31,22,VK_S,0x53,31,31,XK_s,0x0073 +KEY_D,32,ANSI_D,0x2,32,35,35,32,32,7,VK_D,0x44,32,32,XK_D,0x0044 +KEY_D,32,ANSI_D,0x2,32,35,35,32,32,7,VK_D,0x44,32,32,XK_d,0x0064 +KEY_F,33,ANSI_F,0x3,33,43,43,33,33,9,VK_F,0x46,33,33,XK_F,0x0046 +KEY_F,33,ANSI_F,0x3,33,43,43,33,33,9,VK_F,0x46,33,33,XK_f,0x0066 +KEY_G,34,ANSI_G,0x5,34,52,52,34,34,10,VK_G,0x47,34,34,XK_G,0x0047 +KEY_G,34,ANSI_G,0x5,34,52,52,34,34,10,VK_G,0x47,34,34,XK_g,0x0067 +KEY_H,35,ANSI_H,0x4,35,51,51,35,35,11,VK_H,0x48,35,35,XK_H,0x0048 +KEY_H,35,ANSI_H,0x4,35,51,51,35,35,11,VK_H,0x48,35,35,XK_h,0x0068 +KEY_J,36,ANSI_J,0x26,36,59,59,36,36,13,VK_J,0x4a,36,36,XK_J,0x004a +KEY_J,36,ANSI_J,0x26,36,59,59,36,36,13,VK_J,0x4a,36,36,XK_j,0x006a +KEY_K,37,ANSI_K,0x28,37,66,66,37,37,14,VK_K,0x4b,37,37,XK_K,0x004b +KEY_K,37,ANSI_K,0x28,37,66,66,37,37,14,VK_K,0x4b,37,37,XK_K,0x006b +KEY_L,38,ANSI_L,0x25,38,75,75,38,38,15,VK_L,0x4c,38,38,XK_L,0x004c +KEY_L,38,ANSI_L,0x25,38,75,75,38,38,15,VK_L,0x4c,38,38,XK_l,0x006c +KEY_SEMICOLON,39,ANSI_Semicolon,0x29,39,76,76,39,39,51,VK_OEM_1,0xba,39,39,XK_semicolon,0x003b +KEY_APOSTROPHE,40,ANSI_Quote,0x27,40,82,82,40,40,52,VK_OEM_7,0xde,40,40,XK_apostrophe,0x0027 +KEY_GRAVE,41,ANSI_Grave,0x32,41,14,14,41,41,53,VK_OEM_3,0xc0,41,41,XK_grave,0x0060 +KEY_SHIFT,42,Shift,0x38,42,18,18,42,42,225,VK_SHIFT,0x10,42,42,XK_Shift_L,0xffe1 +KEY_LEFTSHIFT,42,Shift,0x38,42,18,18,42,42,225,VK_LSHIFT,0xa0,42,42,XK_Shift_L,0xffe1 +KEY_BACKSLASH,43,ANSI_Backslash,0x2a,43,93,93,43,43,50,VK_OEM_5,0xdc,43,43,XK_backslash,0x005c +KEY_Z,44,ANSI_Z,0x6,44,26,26,44,44,29,VK_Z,0x5a,44,44,XK_Z,0x005a +KEY_Z,44,ANSI_Z,0x6,44,26,26,44,44,29,VK_Z,0x5a,44,44,XK_z,0x007a +KEY_X,45,ANSI_X,0x7,45,34,34,45,45,27,VK_X,0x58,45,45,XK_X,0x0058 +KEY_X,45,ANSI_X,0x7,45,34,34,45,45,27,VK_X,0x58,45,45,XK_x,0x0078 +KEY_C,46,ANSI_C,0x8,46,33,33,46,46,6,VK_C,0x43,46,46,XK_C,0x0043 +KEY_C,46,ANSI_C,0x8,46,33,33,46,46,6,VK_C,0x43,46,46,XK_c,0x0063 +KEY_V,47,ANSI_V,0x9,47,42,42,47,47,25,VK_V,0x56,47,47,XK_V,0x0056 +KEY_V,47,ANSI_V,0x9,47,42,42,47,47,25,VK_V,0x56,47,47,XK_v,0x0076 +KEY_B,48,ANSI_B,0xb,48,50,50,48,48,5,VK_B,0x42,48,48,XK_B,0x0042 +KEY_B,48,ANSI_B,0xb,48,50,50,48,48,5,VK_B,0x42,48,48,XK_b,0x0062 +KEY_N,49,ANSI_N,0x2d,49,49,49,49,49,17,VK_N,0x4e,49,49,XK_N,0x004e +KEY_N,49,ANSI_N,0x2d,49,49,49,49,49,17,VK_N,0x4e,49,49,XK_n,0x006e +KEY_M,50,ANSI_M,0x2e,50,58,58,50,50,16,VK_M,0x4d,50,50,XK_M,0x004d +KEY_M,50,ANSI_M,0x2e,50,58,58,50,50,16,VK_M,0x4d,50,50,XK_m,0x006d +KEY_COMMA,51,ANSI_Comma,0x2b,51,65,65,51,51,54,VK_OEM_COMMA,0xbc,51,51,XK_comma,0x002c +KEY_DOT,52,ANSI_Period,0x2f,52,73,73,52,52,55,VK_OEM_PERIOD,0xbe,52,52,XK_period,0x002e +KEY_SLASH,53,ANSI_Slash,0x2c,53,74,74,53,53,56,VK_OEM_2,0xbf,53,53,XK_slash,0x002f +KEY_RIGHTSHIFT,54,RightShift,0x3c,54,89,89,54,54,229,VK_RSHIFT,0xa1,54,54,XK_Shift_R,0xffe2 +KEY_KPASTERISK,55,ANSI_KeypadMultiply,0x43,55,124,126,55,55,85,VK_MULTIPLY,0x6a,55,55,XK_multiply,0x00d7 +KEY_LEFTALT,56,Option,0x3a,56,17,25,56,56,226,VK_LMENU,0xa4,56,56,XK_Alt_L,0xffe9 +KEY_LEFTALT,56,Option,0x3a,56,17,25,56,56,226,VK_MENU,0x12,56,56,XK_Alt_L,0xffe9 +KEY_SPACE,57,Space,0x31,57,41,41,57,57,44,VK_SPACE,0x20,57,57,XK_space,0x0020 +KEY_CAPSLOCK,58,CapsLock,0x39,58,88,20,58,58,57,VK_CAPITAL,0x14,58,58,XK_Caps_Lock,0xffe5 +KEY_F1,59,F1,0x7a,59,5,7,59,59,58,VK_F1,0x70,59,59,XK_F1,0xffbe +KEY_F2,60,F2,0x78,60,6,15,60,60,59,VK_F2,0x71,60,60,XK_F2,0xffbf +KEY_F3,61,F3,0x63,61,4,23,61,61,60,VK_F3,0x72,61,61,XK_F3,0xffc0 +KEY_F4,62,F4,0x76,62,12,31,62,62,61,VK_F4,0x73,62,62,XK_F4,0xffc1 +KEY_F5,63,F5,0x60,63,3,39,63,63,62,VK_F5,0x74,63,63,XK_F5,0xffc2 +KEY_F6,64,F6,0x61,64,11,47,64,64,63,VK_F6,0x75,64,64,XK_F6,0xffc3 +KEY_F7,65,F7,0x62,65,259,55,65,65,64,VK_F7,0x76,65,65,XK_F7,0xffc4 +KEY_F8,66,F8,0x64,66,10,63,66,66,65,VK_F8,0x77,66,66,XK_F8,0xffc5 +KEY_F9,67,F9,0x65,67,1,71,67,67,66,VK_F9,0x78,67,67,XK_F9,0xffc6 +KEY_F10,68,F10,0x6d,68,9,79,68,68,67,VK_F10,0x79,68,68,XK_F10,0xffc7 +KEY_NUMLOCK,69,,,69,119,118,69,69,83,VK_NUMLOCK,0x90,69,69,XK_Num_Lock,0xff7f +KEY_SCROLLLOCK,70,,,70,126,95,70,70,71,VK_SCROLL,0x91,70,70,XK_Scroll_Lock,0xff14 +KEY_KP7,71,ANSI_Keypad7,0x59,71,108,108,71,71,95,VK_NUMPAD7,0x67,71,71,XK_KP_7,0xffb7 +KEY_KP8,72,ANSI_Keypad8,0x5b,72,117,117,72,72,96,VK_NUMPAD8,0x68,72,72,XK_KP_8,0xffb8 +KEY_KP9,73,ANSI_Keypad9,0x5c,73,125,125,73,73,97,VK_NUMPAD9,0x69,73,73,XK_KP_9,0xffb9 +KEY_KPMINUS,74,ANSI_KeypadMinus,0x4e,74,123,132,74,74,86,VK_SUBTRACT,0x6d,74,74,XK_KP_Subtract,0xffad +KEY_KP4,75,ANSI_Keypad4,0x56,75,107,107,75,75,92,VK_NUMPAD4,0x64,75,75,XK_KP_4,0xffb4 +KEY_KP5,76,ANSI_Keypad5,0x57,76,115,115,76,76,93,VK_NUMPAD5,0x65,76,76,XK_KP_5,0xffb5 +KEY_KP6,77,ANSI_Keypad6,0x58,77,116,116,77,77,94,VK_NUMPAD6,0x66,77,77,XK_KP_6,0xffb6 +KEY_KPPLUS,78,ANSI_KeypadPlus,0x45,78,121,124,78,78,87,VK_ADD,0x6b,78,78,XK_KP_Add,0xffab +KEY_KP1,79,ANSI_Keypad1,0x53,79,105,105,79,79,89,VK_NUMPAD1,0x61,79,79,XK_KP_1,0xffb1 +KEY_KP2,80,ANSI_Keypad2,0x54,80,114,114,80,80,90,VK_NUMPAD2,0x62,80,80,XK_KP_2,0xffb2 +KEY_KP3,81,ANSI_Keypad3,0x55,81,122,122,81,81,91,VK_NUMPAD3,0x63,81,81,XK_KP_3,0xffb3 +KEY_KP0,82,ANSI_Keypad0,0x52,82,112,112,82,82,98,VK_NUMPAD0,0x60,82,82,XK_KP_0,0xffb0 +KEY_KPDOT,83,ANSI_KeypadDecimal,0x41,83,113,113,83,83,99,VK_DECIMAL,0x6e,83,83,XK_KP_Decimal,0xffae +,84,,,,,,,84,,,,, +KEY_ZENKAKUHANKAKU,85,,,118,95,,,118,148,,,, +KEY_102ND,86,,,86,97,19,,86,100,VK_OEM_102,0xe1,, +KEY_F11,87,F11,0x67,87,120,86,101,87,68,VK_F11,0x7a,, +KEY_F12,88,F12,0x6f,88,7,94,102,88,69,VK_F12,0x7b,, +KEY_RO,89,,,115,81,,,115,135,,,, +KEY_KATAKANA,90,JIS_Kana????,0x68,120,99,,,120,146,VK_KANA,0x15,, +KEY_HIRAGANA,91,,,119,98,,,119,147,,,, +KEY_HENKAN,92,,,121,100,134,,121,138,,,, +KEY_KATAKANAHIRAGANA,93,,,112,19,135,,112,136,,,0xc8,0xc8 +KEY_MUHENKAN,94,,,123,103,133,,123,139,,,, +KEY_KPJPCOMMA,95,JIS_KeypadComma,0x5f,92,39,,,92,140,,,,,XK_KP_Separator,0xffac +KEY_KPENTER,96,ANSI_KeypadEnter,0x4c,,158,121,,284,88,,,0x64,0x64,XK_KP_Enter,0xff8d +KEY_RIGHTCTRL,97,RightControl,0x3e,,,88,,285,228,VK_RCONTROL,0xa3,0x65,0x65,XK_Control_R,0xffe4 +KEY_KPSLASH,98,ANSI_KeypadDivide,0x4b,,181,119,,309,84,VK_DIVIDE,0x6f,0x68,0x68,XK_KP_Divide,0xffaf +KEY_SYSRQ,99,,,84,260,87,,84,70,"VK_SNAPSHOT ???",0x2c,0x67,0x67,XK_Sys_Req,0xff15 +KEY_RIGHTALT,100,RightOption,0x3d,,,57,,312,230,VK_RMENU,0xa5,0x69,0x69,XK_Alt_R,0xffea +KEY_LINEFEED,101,,,,,,,91,,,,, +KEY_HOME,102,Home,0x73,,224,110,,327,74,VK_HOME,0x24,0x59,0x59,XK_Home,0xff50 +KEY_UP,103,UpArrow,0x7e,,236,99,109,328,82,VK_UP,0x26,0x5a,0x5a,XK_Up,0xff52 +KEY_PAGEUP,104,PageUp,0x74,,201,111,,329,75,VK_PRIOR,0x21,0x5b,0x5b,XK_Page_Up,0xff55 +KEY_LEFT,105,LeftArrow,0x7b,,203,97,111,331,80,VK_LEFT,0x25,0x5c,0x5c,XK_Left,0xff51 +KEY_RIGHT,106,RightArrow,0x7c,,205,106,112,333,79,VK_RIGHT,0x27,0x5e,0x5e,XK_Right,0xff53 +KEY_END,107,End,0x77,,225,101,,335,77,VK_END,0x23,0x5f,0x5f,XK_End,0xff57 +KEY_DOWN,108,DownArrow,0x7d,,254,96,110,336,81,VK_DOWN,0x28,0x60,0x60,XK_Down,0xff54 +KEY_PAGEDOWN,109,PageDown,0x79,,243,109,,337,78,VK_NEXT,0x22,0x61,0x61,XK_Page_Down,0xff56 +KEY_INSERT,110,,,,210,103,107,338,73,VK_INSERT,0x2d,0x62,0x62,XK_Insert,0xff63 +KEY_DELETE,111,ForwardDelete,0x75,,244,100,108,339,76,VK_DELETE,0x2e,0x63,0x63,XK_Delete,0xffff +KEY_MACRO,112,,,,239,142,,367,,,,, +KEY_MUTE,113,Mute,0x4a,,251,156,,288,239,VK_VOLUME_MUTE,0xad,,, +KEY_VOLUMEDOWN,114,VolumeDown,0x49,,,157,,302,238,VK_VOLUME_DOWN,0xae,, +KEY_VOLUMEUP,115,VolumeUp,0x48,,233,149,,304,237,VK_VOLUME_UP,0xaf,, +KEY_POWER,116,,,,,,,350,102,,,, +KEY_KPEQUAL,117,ANSI_KeypadEquals,0x51,89,15,,,89,103,,,0x76,0x76,XK_KP_Equal,0xffbd +KEY_KPPLUSMINUS,118,,,,206,,,334,,,,, +KEY_PAUSE,119,,,,198,98,,326,72,VK_PAUSE,0x013,0x66,0x66,XK_Pause,0xff13 +KEY_SCALE,120,,,,,,,267,,,,, +KEY_KPCOMMA,121,ANSI_KeypadClear????,0x47,126,109,,,126,133,VK_SEPARATOR??,0x6c,, +KEY_HANGEUL,122,,,,,,,,144,VK_HANGEUL,0x15,, +KEY_HANJA,123,,,,,,,269,145,VK_HANJA,0x19,, +KEY_YEN,124,JIS_Yen,0x5d,125,106,,,125,137,,,0x7d,0x7d +KEY_LEFTMETA,125,Command,0x37,,,139,,347,227,VK_LWIN,0x5b,0x6b,0x6b,XK_Meta_L,0xffe7 +KEY_RIGHTMETA,126,,,,,140,,348,231,VK_RWIN,0x5c,0x6c,0x6c,XK_Meta_R,0xffe8 +KEY_COMPOSE,127,Function,0x3f,,,141,,349,101,VK_APPS,0x5d,0x6d,0x6d +KEY_STOP,128,,,,,10,,360,243,VK_BROWSER_STOP,0xa9,, +KEY_AGAIN,129,,,,,11,,261,121,,,, +KEY_PROPS,130,,,,,12,,262,118,,,, +KEY_UNDO,131,,,,,16,,263,122,,,, +KEY_FRONT,132,,,,,,,268,119,,,, +KEY_COPY,133,,,,,24,,376,124,,,, +KEY_OPEN,134,,,,,32,,100,116,,,, +KEY_PASTE,135,,,,,40,,101,125,,,, +KEY_FIND,136,,,,,48,,321,244,,,, +KEY_CUT,137,,,,,56,,316,123,,,, +KEY_HELP,138,,,,,9,,373,117,VK_HELP,0x2f,,,XK_Help,0xff6a +KEY_MENU,139,,,,,145,,286,,,,, +KEY_CALC,140,,,,174,163,,289,251,,,, +KEY_SETUP,141,,,,,,,102,,,,, +KEY_SLEEP,142,,,,,,,351,248,VK_SLEEP,0x5f,, +KEY_WAKEUP,143,,,,,,,355,,,,, +KEY_FILE,144,,,,,,,103,,,,, +KEY_SENDFILE,145,,,,,,,104,,,,, +KEY_DELETEFILE,146,,,,,,,105,,,,, +KEY_XFER,147,,,,,162,,275,,,,, +KEY_PROG1,148,,,,,160,,287,,,,, +KEY_PROG2,149,,,,,161,,279,,,,, +KEY_WWW,150,,,,,,,258,240,,,, +KEY_MSDOS,151,,,,,,,106,,,,, +KEY_SCREENLOCK,152,,,,,150,,274,249,,,, +KEY_DIRECTION,153,,,,,,,107,,,,, +KEY_CYCLEWINDOWS,154,,,,,155,,294,,,,, +KEY_MAIL,155,,,,,,,364,,,,, +KEY_BOOKMARKS,156,,,,,,,358,,,,, +KEY_COMPUTER,157,,,,,,,363,,,,, +KEY_BACK,158,,,,,,,362,241,VK_BROWSER_BACK,0xa6,, +KEY_FORWARD,159,,,,,,,361,242,VK_BROWSER_FORWARD,0xa7,, +KEY_CLOSECD,160,,,,,154,,291,,,,, +KEY_EJECTCD,161,,,,,,,108,236,,,, +KEY_EJECTCLOSECD,162,,,,,,,381,,,,, +KEY_NEXTSONG,163,,,,241,147,,281,235,VK_MEDIA_NEXT_TRACK,0xb0,, +KEY_PLAYPAUSE,164,,,,173,,,290,232,VK_MEDIA_PLAY_PAUSE,0xb3,, +KEY_PREVIOUSSONG,165,,,,250,148,,272,234,VK_MEDIA_PREV_TRACK,0xb1,, +KEY_STOPCD,166,,,,164,152,,292,233,VK_MEDIA_STOP,0xb2,, +KEY_RECORD,167,,,,,158,,305,,,,, +KEY_REWIND,168,,,,,159,,280,,,,, +KEY_PHONE,169,,,,,,,99,,,,, +KEY_ISO,170,ISO_Section,0xa,,,,,112,,,,, +KEY_CONFIG,171,,,,,,,257,,,,, +KEY_HOMEPAGE,172,,,,178,151,,306,,VK_BROWSER_HOME,0xac,, +KEY_REFRESH,173,,,,,,,359,250,VK_BROWSER_REFRESH,0xa8,, +KEY_EXIT,174,,,,,,,113,,,,, +KEY_MOVE,175,,,,,,,114,,,,, +KEY_EDIT,176,,,,,,,264,247,,,, +KEY_SCROLLUP,177,,,,,,,117,245,,,, +KEY_SCROLLDOWN,178,,,,,,,271,246,,,, +KEY_KPLEFTPAREN,179,,,,,,,374,182,,,, +KEY_KPRIGHTPAREN,180,,,,,,,379,183,,,, +KEY_NEW,181,,,,,,,265,,,,, +KEY_REDO,182,,,,,,,266,,,,, +KEY_F13,183,F13,0x69,93,47,127,,93,104,VK_F13,0x7c,0x6e,0x6e +KEY_F14,184,F14,0x6b,94,55,128,,94,105,VK_F14,0x7d,0x6f,0x6f +KEY_F15,185,F15,0x71,95,63,129,,95,106,VK_F15,0x7e,0x70,0x70 +KEY_F16,186,F16,0x6a,,,130,,85,107,VK_F16,0x7f,0x71,0x71 +KEY_F17,187,F17,0x40,,,131,,259,108,VK_F17,0x80,0x72,0x72 +KEY_F18,188,F18,0x4f,,,,,375,109,VK_F18,0x81,, +KEY_F19,189,F19,0x50,,,,,260,110,VK_F19,0x82,, +KEY_F20,190,F20,0x5a,,,,,90,111,VK_F20,0x83,, +KEY_F21,191,,,,,,,116,112,VK_F21,0x84,, +KEY_F22,192,,,,,,,377,113,VK_F22,0x85,, +KEY_F23,193,,,,,,,109,114,VK_F23,0x86,, +KEY_F24,194,,,,,,,111,115,VK_F24,0x87,, +,195,,,,,,,277,,,,, +,196,,,,,,,278,,,,, +,197,,,,,,,282,,,,, +,198,,,,,,,283,,,,, +,199,,,,,,,295,,,,, +KEY_PLAYCD,200,,,,,,,296,,,,, +KEY_PAUSECD,201,,,,,,,297,,,,, +KEY_PROG3,202,,,,,,,299,,,,, +KEY_PROG4,203,,,,,,,300,,,,, +KEY_DASHBOARD,204,,,,,,,301,,,,, +KEY_SUSPEND,205,,,,,,,293,,,,, +KEY_CLOSE,206,,,,,,,303,,,,, +KEY_PLAY,207,,,,,,,307,,VK_PLAY,0xfa,, +KEY_FASTFORWARD,208,,,,,,,308,,,,, +KEY_BASSBOOST,209,,,,,,,310,,,,, +KEY_PRINT,210,,,,,,,313,,VK_PRINT,0x2a,, +KEY_HP,211,,,,,,,314,,,,, +KEY_CAMERA,212,,,,,,,315,,,,, +KEY_SOUND,213,,,,,,,317,,,,, +KEY_QUESTION,214,,,,,,,318,,,,, +KEY_EMAIL,215,,,,,,,319,,VK_LAUNCH_MAIL,0xb4,, +KEY_CHAT,216,,,,,,,320,,,,, +KEY_SEARCH,217,,,,,,,357,,VK_BROWSER_SEARCH,0xaa,, +KEY_CONNECT,218,,,,,,,322,,,,, +KEY_FINANCE,219,,,,,,,323,,,,, +KEY_SPORT,220,,,,,,,324,,,,, +KEY_SHOP,221,,,,,,,325,,,,, +KEY_ALTERASE,222,,,,,,,276,,,,, +KEY_CANCEL,223,,,,,,,330,,,,, +KEY_BRIGHTNESSDOWN,224,,,,,,,332,,,,, +KEY_BRIGHTNESSUP,225,,,,,,,340,,,,, +KEY_MEDIA,226,,,,,,,365,,,,, +KEY_SWITCHVIDEOMODE,227,,,,,,,342,,,,, +KEY_KBDILLUMTOGGLE,228,,,,,,,343,,,,, +KEY_KBDILLUMDOWN,229,,,,,,,344,,,,, +KEY_KBDILLUMUP,230,,,,,,,345,,,,, +KEY_SEND,231,,,,,,,346,,,,, +KEY_REPLY,232,,,,,,,356,,,,, +KEY_FORWARDMAIL,233,,,,,,,270,,,,, +KEY_SAVE,234,,,,,,,341,,,,, +KEY_DOCUMENTS,235,,,,,,,368,,,,, +KEY_BATTERY,236,,,,,,,369,,,,, +KEY_BLUETOOTH,237,,,,,,,370,,,,, +KEY_WLAN,238,,,,,,,371,,,,, +KEY_UWB,239,,,,,,,372,,,,, +KEY_UNKNOWN,240,,,,,,,,,,,, +KEY_VIDEO_NEXT,241,,,,,,,,,,,, +KEY_VIDEO_PREV,242,,,,,,,,,,,, +KEY_BRIGHTNESS_CYCLE,243,,,,,,,,,,,, +KEY_BRIGHTNESS_ZERO,244,,,,,,,,,,,, +KEY_DISPLAY_OFF,245,,,,,,,,,,,, +KEY_WIMAX,246,,,,,,,,,,,, +,247,,,,,,,,,,,, +,248,,,,,,,,,,,, +,249,,,,,,,,,,,, +,250,,,,,,,,,,,, +,251,,,,,,,,,,,, +,252,,,,,,,,,,,, +,253,,,,,,,,,,,, +,254,,,,,,,,,,,, +,255,,,,182,,,,,,,, +BTN_MISC,0x100,,,,,,,,,,,, +BTN_0,0x100,,,,,,,,,VK_LBUTTON,0x01,, +BTN_1,0x101,,,,,,,,,VK_RBUTTON,0x02,, +BTN_2,0x102,,,,,,,,,VK_MBUTTON,0x04,, +BTN_3,0x103,,,,,,,,,VK_XBUTTON1,0x05,, +BTN_4,0x104,,,,,,,,,VK_XBUTTON2,0x06,, +BTN_5,0x105,,,,,,,,,,,, +BTN_6,0x106,,,,,,,,,,,, +BTN_7,0x107,,,,,,,,,,,, +BTN_8,0x108,,,,,,,,,,,, +BTN_9,0x109,,,,,,,,,,,, +BTN_MOUSE,0x110,,,,,,,,,,,, +BTN_LEFT,0x110,,,,,,,,,,,, +BTN_RIGHT,0x111,,,,,,,,,,,, +BTN_MIDDLE,0x112,,,,,,,,,,,, +BTN_SIDE,0x113,,,,,,,,,,,, +BTN_EXTRA,0x114,,,,,,,,,,,, +BTN_FORWARD,0x115,,,,,,,,,,,, +BTN_BACK,0x116,,,,,,,,,,,, +BTN_TASK,0x117,,,,,,,,,,,, +BTN_JOYSTICK,0x120,,,,,,,,,,,, +BTN_TRIGGER,0x120,,,,,,,,,,,, +BTN_THUMB,0x121,,,,,,,,,,,, +BTN_THUMB2,0x122,,,,,,,,,,,, +BTN_TOP,0x123,,,,,,,,,,,, +BTN_TOP2,0x124,,,,,,,,,,,, +BTN_PINKIE,0x125,,,,,,,,,,,, +BTN_BASE,0x126,,,,,,,,,,,, +BTN_BASE2,0x127,,,,,,,,,,,, +BTN_BASE3,0x128,,,,,,,,,,,, +BTN_BASE4,0x129,,,,,,,,,,,, +BTN_BASE5,0x12a,,,,,,,,,,,, +BTN_BASE6,0x12b,,,,,,,,,,,, +BTN_DEAD,0x12f,,,,,,,,,,,, +BTN_GAMEPAD,0x130,,,,,,,,,,,, +BTN_A,0x130,,,,,,,,,,,, +BTN_B,0x131,,,,,,,,,,,, +BTN_C,0x132,,,,,,,,,,,, +BTN_X,0x133,,,,,,,,,,,, +BTN_Y,0x134,,,,,,,,,,,, +BTN_Z,0x135,,,,,,,,,,,, +BTN_TL,0x136,,,,,,,,,,,, +BTN_TR,0x137,,,,,,,,,,,, +BTN_TL2,0x138,,,,,,,,,,,, +BTN_TR2,0x139,,,,,,,,,,,, +BTN_SELECT,0x13a,,,,,,,,,,,, +BTN_START,0x13b,,,,,,,,,,,, +BTN_MODE,0x13c,,,,,,,,,,,, +BTN_THUMBL,0x13d,,,,,,,,,,,, +BTN_THUMBR,0x13e,,,,,,,,,,,, +BTN_DIGI,0x140,,,,,,,,,,,, +BTN_TOOL_PEN,0x140,,,,,,,,,,,, +BTN_TOOL_RUBBER,0x141,,,,,,,,,,,, +BTN_TOOL_BRUSH,0x142,,,,,,,,,,,, +BTN_TOOL_PENCIL,0x143,,,,,,,,,,,, +BTN_TOOL_AIRBRUSH,0x144,,,,,,,,,,,, +BTN_TOOL_FINGER,0x145,,,,,,,,,,,, +BTN_TOOL_MOUSE,0x146,,,,,,,,,,,, +BTN_TOOL_LENS,0x147,,,,,,,,,,,, +BTN_TOUCH,0x14a,,,,,,,,,,,, +BTN_STYLUS,0x14b,,,,,,,,,,,, +BTN_STYLUS2,0x14c,,,,,,,,,,,, +BTN_TOOL_DOUBLETAP,0x14d,,,,,,,,,,,, +BTN_TOOL_TRIPLETAP,0x14e,,,,,,,,,,,, +BTN_TOOL_QUADTAP,0x14f,,,,,,,,,,,, +BTN_WHEEL,0x150,,,,,,,,,,,, +BTN_GEAR_DOWN,0x150,,,,,,,,,,,, +BTN_GEAR_UP,0x151,,,,,,,,,,,, +KEY_OK,0x160,,,,,,,,,,,, +KEY_SELECT,0x161,,,,,,,,,VK_SELECT,0x29,,,XK_Select,0xff60 +KEY_GOTO,0x162,,,,,,,,,,,, +KEY_CLEAR,0x163,,,,,,,,,,,, +KEY_POWER2,0x164,,,,,,,,,,,, +KEY_OPTION,0x165,,,,,,,,,,,, +KEY_INFO,0x166,,,,,,,,,,,, +KEY_TIME,0x167,,,,,,,,,,,, +KEY_VENDOR,0x168,,,,,,,,,,,, +KEY_ARCHIVE,0x169,,,,,,,,,,,, +KEY_PROGRAM,0x16a,,,,,,,,,,,, +KEY_CHANNEL,0x16b,,,,,,,,,,,, +KEY_FAVORITES,0x16c,,,,,,,,,VK_BROWSER_FAVOURITES,0xab,, +KEY_EPG,0x16d,,,,,,,,,,,, +KEY_PVR,0x16e,,,,,,,,,,,, +KEY_MHP,0x16f,,,,,,,,,,,, +KEY_LANGUAGE,0x170,,,,,,,,,,,, +KEY_TITLE,0x171,,,,,,,,,,,, +KEY_SUBTITLE,0x172,,,,,,,,,,,, +KEY_ANGLE,0x173,,,,,,,,,,,, +KEY_ZOOM,0x174,,,,,,,,,VK_ZOOM,0xfb,, +KEY_MODE,0x175,,,,,,,,,,,, +KEY_KEYBOARD,0x176,,,,,,,,,,,, +KEY_SCREEN,0x177,,,,,,,,,,,, +KEY_PC,0x178,,,,,,,,,,,, +KEY_TV,0x179,,,,,,,,,,,, +KEY_TV2,0x17a,,,,,,,,,,,, +KEY_VCR,0x17b,,,,,,,,,,,, +KEY_VCR2,0x17c,,,,,,,,,,,, +KEY_SAT,0x17d,,,,,,,,,,,, +KEY_SAT2,0x17e,,,,,,,,,,,, +KEY_CD,0x17f,,,,,,,,,,,, +KEY_TAPE,0x180,,,,,,,,,,,, +KEY_RADIO,0x181,,,,,,,,,,,, +KEY_TUNER,0x182,,,,,,,,,,,, +KEY_PLAYER,0x183,,,,,,,,,,,, +KEY_TEXT,0x184,,,,,,,,,,,, +KEY_DVD,0x185,,,,,,,,,,,, +KEY_AUX,0x186,,,,,,,,,,,, +KEY_MP3,0x187,,,,,,,,,,,, +KEY_AUDIO,0x188,,,,,,,,,,,, +KEY_VIDEO,0x189,,,,,,,,,,,, +KEY_DIRECTORY,0x18a,,,,,,,,,,,, +KEY_LIST,0x18b,,,,,,,,,,,, +KEY_MEMO,0x18c,,,,,,,,,,,, +KEY_CALENDAR,0x18d,,,,,,,,,,,, +KEY_RED,0x18e,,,,,,,,,,,, +KEY_GREEN,0x18f,,,,,,,,,,,, +KEY_YELLOW,0x190,,,,,,,,,,,, +KEY_BLUE,0x191,,,,,,,,,,,, +KEY_CHANNELUP,0x192,,,,,,,,,,,, +KEY_CHANNELDOWN,0x193,,,,,,,,,,,, +KEY_FIRST,0x194,,,,,,,,,,,, +KEY_LAST,0x195,,,,,,,,,,,, +KEY_AB,0x196,,,,,,,,,,,, +KEY_NEXT,0x197,,,,,,,,,,,, +KEY_RESTART,0x198,,,,,,,,,,,, +KEY_SLOW,0x199,,,,,,,,,,,, +KEY_SHUFFLE,0x19a,,,,,,,,,,,, +KEY_BREAK,0x19b,,,,,,,,,,,, +KEY_PREVIOUS,0x19c,,,,,,,,,,,, +KEY_DIGITS,0x19d,,,,,,,,,,,, +KEY_TEEN,0x19e,,,,,,,,,,,, +KEY_TWEN,0x19f,,,,,,,,,,,, +KEY_VIDEOPHONE,0x1a0,,,,,,,,,,,, +KEY_GAMES,0x1a1,,,,,,,,,,,, +KEY_ZOOMIN,0x1a2,,,,,,,,,,,, +KEY_ZOOMOUT,0x1a3,,,,,,,,,,,, +KEY_ZOOMRESET,0x1a4,,,,,,,,,,,, +KEY_WORDPROCESSOR,0x1a5,,,,,,,,,,,, +KEY_EDITOR,0x1a6,,,,,,,,,,,, +KEY_SPREADSHEET,0x1a7,,,,,,,,,,,, +KEY_GRAPHICSEDITOR,0x1a8,,,,,,,,,,,, +KEY_PRESENTATION,0x1a9,,,,,,,,,,,, +KEY_DATABASE,0x1aa,,,,,,,,,,,, +KEY_NEWS,0x1ab,,,,,,,,,,,, +KEY_VOICEMAIL,0x1ac,,,,,,,,,,,, +KEY_ADDRESSBOOK,0x1ad,,,,,,,,,,,, +KEY_MESSENGER,0x1ae,,,,,,,,,,,, +KEY_DISPLAYTOGGLE,0x1af,,,,,,,,,,,, +KEY_SPELLCHECK,0x1b0,,,,,,,,,,,, +KEY_LOGOFF,0x1b1,,,,,,,,,,,, +KEY_DOLLAR,0x1b2,,,,,,,,,,,, +KEY_EURO,0x1b3,,,,,,,,,,,, +KEY_FRAMEBACK,0x1b4,,,,,,,,,,,, +KEY_FRAMEFORWARD,0x1b5,,,,,,,,,,,, +KEY_CONTEXT_MENU,0x1b6,,,,,,,,,,,, +KEY_MEDIA_REPEAT,0x1b7,,,,,,,,,,,, +KEY_DEL_EOL,0x1c0,,,,,,,,,,,, +KEY_DEL_EOS,0x1c1,,,,,,,,,,,, +KEY_INS_LINE,0x1c2,,,,,,,,,,,, +KEY_DEL_LINE,0x1c3,,,,,,,,,,,, +KEY_FN,0x1d0,,,,,,,,,,,, +KEY_FN_ESC,0x1d1,,,,,,,,,,,, +KEY_FN_F1,0x1d2,,,,,,,,,,,, +KEY_FN_F2,0x1d3,,,,,,,,,,,, +KEY_FN_F3,0x1d4,,,,,,,,,,,, +KEY_FN_F4,0x1d5,,,,,,,,,,,, +KEY_FN_F5,0x1d6,,,,,,,,,,,, +KEY_FN_F6,0x1d7,,,,,,,,,,,, +KEY_FN_F7,0x1d8,,,,,,,,,,,, +KEY_FN_F8,0x1d9,,,,,,,,,,,, +KEY_FN_F9,0x1da,,,,,,,,,,,, +KEY_FN_F10,0x1db,,,,,,,,,,,, +KEY_FN_F11,0x1dc,,,,,,,,,,,, +KEY_FN_F12,0x1dd,,,,,,,,,,,, +KEY_FN_1,0x1de,,,,,,,,,,,, +KEY_FN_2,0x1df,,,,,,,,,,,, +KEY_FN_D,0x1e0,,,,,,,,,,,, +KEY_FN_E,0x1e1,,,,,,,,,,,, +KEY_FN_F,0x1e2,,,,,,,,,,,, +KEY_FN_S,0x1e3,,,,,,,,,,,, +KEY_FN_B,0x1e4,,,,,,,,,,,, +KEY_BRL_DOT1,0x1f1,,,,,,,,,,,, +KEY_BRL_DOT2,0x1f2,,,,,,,,,,,, +KEY_BRL_DOT3,0x1f3,,,,,,,,,,,, +KEY_BRL_DOT4,0x1f4,,,,,,,,,,,, +KEY_BRL_DOT5,0x1f5,,,,,,,,,,,, +KEY_BRL_DOT6,0x1f6,,,,,,,,,,,, +KEY_BRL_DOT7,0x1f7,,,,,,,,,,,, +KEY_BRL_DOT8,0x1f8,,,,,,,,,,,, +KEY_BRL_DOT9,0x1f9,,,,,,,,,,,, +KEY_BRL_DOT10,0x1fa,,,,,,,,,,,, +KEY_NUMERIC_0,0x200,,,,,,,,,,,, +KEY_NUMERIC_1,0x201,,,,,,,,,,,, +KEY_NUMERIC_2,0x202,,,,,,,,,,,, +KEY_NUMERIC_3,0x203,,,,,,,,,,,, +KEY_NUMERIC_4,0x204,,,,,,,,,,,, +KEY_NUMERIC_5,0x205,,,,,,,,,,,, +KEY_NUMERIC_6,0x206,,,,,,,,,,,, +KEY_NUMERIC_7,0x207,,,,,,,,,,,, +KEY_NUMERIC_8,0x208,,,,,,,,,,,, +KEY_NUMERIC_9,0x209,,,,,,,,,,,, +KEY_NUMERIC_STAR,0x20a,,,,,,,,,,,, +KEY_NUMERIC_POUND,0x20b,,,,,,,,,,,, +KEY_RFKILL,0x20c,,,,,,,,,,,, diff --git a/src/map-file b/src/map-file new file mode 100644 index 0000000..8618f6e --- /dev/null +++ b/src/map-file @@ -0,0 +1,151 @@ +SPICEGTK_1 { +global: +spice_audio_get; +spice_audio_get_type; +spice_audio_new; +spice_channel_connect; +spice_channel_destroy; +spice_channel_disconnect; +spice_channel_event_get_type; +spice_channel_flush_async; +spice_channel_flush_finish; +spice_channel_get_error; +spice_channel_get_type; +spice_channel_new; +spice_channel_open_fd; +spice_channel_set_capability; +spice_channel_string_to_type; +spice_channel_test_capability; +spice_channel_test_common_capability; +spice_channel_type_to_string; +spice_client_error_quark; +spice_cursor_channel_get_type; +spice_display_change_preferred_compression; +spice_display_channel_get_type; +spice_display_get_gl_scanout; +spice_display_get_grab_keys; +spice_display_get_pixbuf; +spice_display_get_primary; +spice_display_get_type; +spice_display_gl_draw_done; +spice_display_key_event_get_type; +spice_display_mouse_ungrab; +spice_display_new; +spice_display_new_with_monitor; +spice_display_send_keys; +spice_display_set_grab_keys; +spice_file_transfer_task_cancel; +spice_file_transfer_task_get_filename; +spice_file_transfer_task_get_progress; +spice_file_transfer_task_get_type; +spice_get_option_group; +spice_gl_scanout_free; +spice_gl_scanout_get_type; +spice_grab_sequence_as_string; +spice_grab_sequence_copy; +spice_grab_sequence_free; +spice_grab_sequence_get_type; +spice_grab_sequence_new; +spice_grab_sequence_new_from_string; +spice_g_signal_connect_object; +spice_gtk_session_copy_to_guest; +spice_gtk_session_get; +spice_gtk_session_get_type; +spice_gtk_session_paste_from_guest; +spice_inputs_button_press; +spice_inputs_button_release; +spice_inputs_channel_get_type; +spice_inputs_key_press; +spice_inputs_key_press_and_release; +spice_inputs_key_release; +spice_inputs_lock_get_type; +spice_inputs_motion; +spice_inputs_position; +spice_inputs_set_key_locks; +spice_main_agent_test_capability; +spice_main_channel_get_type; +spice_main_clipboard_grab; +spice_main_clipboard_notify; +spice_main_clipboard_release; +spice_main_clipboard_request; +spice_main_clipboard_selection_grab; +spice_main_clipboard_selection_notify; +spice_main_clipboard_selection_release; +spice_main_clipboard_selection_request; +spice_main_file_copy_async; +spice_main_file_copy_finish; +spice_main_request_mouse_mode; +spice_main_send_monitor_config; +spice_main_set_display; +spice_main_set_display_enabled; +spice_main_update_display; +spice_main_update_display_enabled; +spice_playback_channel_get_type; +spice_playback_channel_set_delay; +spice_port_channel_get_type; +spice_port_event; +spice_port_write_async; +spice_port_write_finish; +spice_record_channel_get_type; +spice_record_send_data; +spice_session_connect; +spice_session_disconnect; +spice_session_get_channels; +spice_session_get_proxy_uri; +spice_session_get_read_only; +spice_session_get_type; +spice_session_has_channel_type; +spice_session_is_for_migration; +spice_session_migration_get_type; +spice_session_new; +spice_session_open_fd; +spice_session_verify_get_type; +spice_set_session_option; +spice_smartcard_channel_get_type; +spice_smartcard_manager_get; +spice_smartcard_manager_get_readers; +spice_smartcard_manager_get_type; +spice_smartcard_manager_insert_card; +spice_smartcard_manager_remove_card; +spice_smartcard_reader_get_type; +spice_smartcard_reader_insert_card; +spice_smartcard_reader_is_software; +spice_smartcard_reader_remove_card; +spice_uri_get_hostname; +spice_uri_get_password; +spice_uri_get_port; +spice_uri_get_scheme; +spice_uri_get_type; +spice_uri_get_user; +spice_uri_set_hostname; +spice_uri_set_password; +spice_uri_set_port; +spice_uri_set_scheme; +spice_uri_set_user; +spice_uri_to_string; +spice_usb_device_get_description; +spice_usb_device_get_libusb_device; +spice_usb_device_get_type; +spice_usb_device_manager_can_redirect_device; +spice_usb_device_manager_connect_device_async; +spice_usb_device_manager_connect_device_finish; +spice_usb_device_manager_disconnect_device; +spice_usb_device_manager_disconnect_device_async; +spice_usb_device_manager_disconnect_device_finish; +spice_usb_device_manager_get; +spice_usb_device_manager_get_devices; +spice_usb_device_manager_get_devices_with_filter; +spice_usb_device_manager_get_type; +spice_usb_device_manager_is_device_connected; +spice_usb_device_manager_is_redirecting; +spice_usb_device_widget_get_type; +spice_usb_device_widget_new; +spice_usbredir_channel_get_type; +spice_util_get_debug; +spice_util_get_version_string; +spice_util_set_debug; +spice_uuid_to_string; +spice_webdav_channel_get_type; +local: +*; +}; diff --git a/src/smartcard-manager-priv.h b/src/smartcard-manager-priv.h new file mode 100644 index 0000000..409c1c5 --- /dev/null +++ b/src/smartcard-manager-priv.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SMARTCARD_MANAGER_PRIV_H__ +#define __SMARTCARD_MANAGER_PRIV_H__ + +#include "config.h" +#include +#include "spice-session.h" + +G_BEGIN_DECLS + +void spice_smartcard_manager_init_async(SpiceSession *session, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer opaque); +gboolean spice_smartcard_manager_init_finish(SpiceSession *session, + GAsyncResult *result, + GError **err); + +G_END_DECLS + +#endif /* __SMARTCARD_MANAGER_PRIV_H__ */ diff --git a/src/smartcard-manager.c b/src/smartcard-manager.c new file mode 100644 index 0000000..708f976 --- /dev/null +++ b/src/smartcard-manager.c @@ -0,0 +1,721 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#ifdef USE_SMARTCARD_012 +#include +#include +#include +#else +#ifdef USE_SMARTCARD +#include +#endif +#endif + +#include "spice-client.h" +#include "smartcard-manager.h" +#include "smartcard-manager-priv.h" +#include "spice-marshal.h" + +/** + * SECTION:smartcard-manager + * @short_description: smartcard management + * @title: Spice Smartcard Manager + * @section_id: + * @see_also: + * @stability: Stable + * @include: spice-client.h + * + * #SpiceSmartcardManager monitors smartcard reader plugging/unplugging, + * and smartcard insertions/removals. It also provides methods to handle + * software smartcards (to emulate a smartcard reader/smartcard on the + * guest using 3 certificates available to the client). + */ + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_SMARTCARD_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_SMARTCARD_MANAGER, SpiceSmartcardManagerPrivate)) + +struct _SpiceSmartcardManagerPrivate { + guint monitor_id; + + /* software smartcard reader, the certificates to use for this reader + * were given at the channel creation time. This reader has no physical + * existence, it's all controlled by explicit software + * insertion/removal of cards + */ +#ifdef USE_SMARTCARD + VReader *software_reader; +#endif +}; + +G_DEFINE_TYPE(SpiceSmartcardManager, spice_smartcard_manager, G_TYPE_OBJECT) +#ifdef USE_SMARTCARD +G_DEFINE_BOXED_TYPE(VReader, spice_smartcard_reader, vreader_reference, vreader_free) +#else +typedef GObject VReader; +G_DEFINE_BOXED_TYPE(VReader, spice_smartcard_reader, g_object_ref, g_object_unref) +#endif + +/* Properties */ +enum { + PROP_0, +}; + +/* Signals */ +enum { + SPICE_SMARTCARD_MANAGER_READER_ADDED, + SPICE_SMARTCARD_MANAGER_READER_REMOVED, + SPICE_SMARTCARD_MANAGER_CARD_INSERTED, + SPICE_SMARTCARD_MANAGER_CARD_REMOVED, + + SPICE_SMARTCARD_MANAGER_LAST_SIGNAL, +}; + +static guint signals[SPICE_SMARTCARD_MANAGER_LAST_SIGNAL]; + +#ifdef USE_SMARTCARD +typedef gboolean (*SmartcardSourceFunc)(VEvent *event, gpointer user_data); +static gboolean smartcard_monitor_dispatch(VEvent *event, gpointer user_data); +#endif + +/* ------------------------------------------------------------------ */ + +static void spice_smartcard_manager_init(SpiceSmartcardManager *smartcard_manager) +{ + SpiceSmartcardManagerPrivate *priv; + + priv = SPICE_SMARTCARD_MANAGER_GET_PRIVATE(smartcard_manager); + smartcard_manager->priv = priv; +} + +static void spice_smartcard_manager_dispose(GObject *gobject) +{ + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_smartcard_manager_parent_class)->dispose) + G_OBJECT_CLASS(spice_smartcard_manager_parent_class)->dispose(gobject); +} + +static void spice_smartcard_manager_finalize(GObject *gobject) +{ + SpiceSmartcardManager *manager = SPICE_SMARTCARD_MANAGER(gobject); + SpiceSmartcardManagerPrivate *priv = manager->priv; + + if (priv->monitor_id != 0) { + g_source_remove(priv->monitor_id); + priv->monitor_id = 0; + } + +#ifdef USE_SMARTCARD + g_clear_pointer(&priv->software_reader, vreader_free); +#endif + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_smartcard_manager_parent_class)->finalize) + G_OBJECT_CLASS(spice_smartcard_manager_parent_class)->finalize(gobject); +} + +static void spice_smartcard_manager_class_init(SpiceSmartcardManagerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * SpiceSmartcardManager::reader-added: + * @manager: the #SpiceSmartcardManager that emitted the signal + * @vreader: #VReader boxed object corresponding to the added reader + * + * The #SpiceSmartcardManager::reader-added signal is emitted whenever + * a new smartcard reader (software or hardware) has been plugged in. + **/ + signals[SPICE_SMARTCARD_MANAGER_READER_ADDED] = + g_signal_new("reader-added", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSmartcardManagerClass, reader_added), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_SMARTCARD_READER); + + /** + * SpiceSmartcardManager::reader-removed: + * @manager: the #SpiceSmartcardManager that emitted the signal + * @vreader: #VReader boxed object corresponding to the removed reader + * + * The #SpiceSmartcardManager::reader-removed signal is emitted whenever + * a smartcard reader (software or hardware) has been removed. + **/ + signals[SPICE_SMARTCARD_MANAGER_READER_REMOVED] = + g_signal_new("reader-removed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSmartcardManagerClass, reader_removed), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_SMARTCARD_READER); + + /** + * SpiceSmartcardManager::card-inserted: + * @manager: the #SpiceSmartcardManager that emitted the signal + * @vreader: #VReader boxed object corresponding to the reader a new + * card was inserted in + * + * The #SpiceSmartcardManager::card-inserted signal is emitted whenever + * a smartcard is inserted in a reader + **/ + signals[SPICE_SMARTCARD_MANAGER_CARD_INSERTED] = + g_signal_new("card-inserted", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSmartcardManagerClass, card_inserted), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_SMARTCARD_READER); + + /** + * SpiceSmartcardManager::card-removed: + * @manager: the #SpiceSmartcardManager that emitted the signal + * @vreader: #VReader boxed object corresponding to the reader a card + * was removed from + * + * The #SpiceSmartcardManager::card-removed signal is emitted whenever + * a smartcard was removed from a reader. + **/ + signals[SPICE_SMARTCARD_MANAGER_CARD_REMOVED] = + g_signal_new("card-removed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSmartcardManagerClass, card_removed), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_SMARTCARD_READER); + gobject_class->dispose = spice_smartcard_manager_dispose; + gobject_class->finalize = spice_smartcard_manager_finalize; + + g_type_class_add_private(klass, sizeof(SpiceSmartcardManagerPrivate)); +} + +/* ------------------------------------------------------------------ */ +/* private api */ + +static SpiceSmartcardManager *spice_smartcard_manager_new(void) +{ + return g_object_new(SPICE_TYPE_SMARTCARD_MANAGER, NULL); +} + +/* ------------------------------------------------------------------ */ +/* public api */ + +/** + * spice_smartcard_manager_get: + * + * #SpiceSmartcardManager is a singleton, use this function to get a pointer + * to it. A new SpiceSmartcardManager instance will be created the first + * time this function is called + * + * Returns: (transfer none): a weak reference to the #SpiceSmartcardManager + */ +SpiceSmartcardManager *spice_smartcard_manager_get(void) +{ + static GOnce manager_singleton_once = G_ONCE_INIT; + + return g_once(&manager_singleton_once, + (GThreadFunc)spice_smartcard_manager_new, + NULL); +} + +#ifdef USE_SMARTCARD +static gboolean smartcard_monitor_dispatch(VEvent *event, gpointer user_data) +{ + g_return_val_if_fail(event != NULL, TRUE); + SpiceSmartcardManager *manager = SPICE_SMARTCARD_MANAGER(user_data); + + switch (event->type) { + case VEVENT_READER_INSERT: + if (spice_smartcard_reader_is_software((SpiceSmartcardReader*)event->reader)) { + g_warn_if_fail(manager->priv->software_reader == NULL); + manager->priv->software_reader = vreader_reference(event->reader); + } + SPICE_DEBUG("smartcard: reader-added"); + g_signal_emit(G_OBJECT(user_data), + signals[SPICE_SMARTCARD_MANAGER_READER_ADDED], + 0, event->reader); + break; + + case VEVENT_READER_REMOVE: + if (spice_smartcard_reader_is_software((SpiceSmartcardReader*)event->reader)) { + g_warn_if_fail(manager->priv->software_reader != NULL); + g_clear_pointer(&manager->priv->software_reader, vreader_free); + } + SPICE_DEBUG("smartcard: reader-removed"); + g_signal_emit(G_OBJECT(user_data), + signals[SPICE_SMARTCARD_MANAGER_READER_REMOVED], + 0, event->reader); + break; + + case VEVENT_CARD_INSERT: + SPICE_DEBUG("smartcard: card-inserted"); + g_signal_emit(G_OBJECT(user_data), + signals[SPICE_SMARTCARD_MANAGER_CARD_INSERTED], + 0, event->reader); + break; + case VEVENT_CARD_REMOVE: + SPICE_DEBUG("smartcard: card-removed"); + g_signal_emit(G_OBJECT(user_data), + signals[SPICE_SMARTCARD_MANAGER_CARD_REMOVED], + 0, event->reader); + break; + case VEVENT_LAST: + break; + } + + return TRUE; +} + +/* ------------------------------------------------------------------ */ +/* smartcard monitoring GSource */ +struct _SmartcardSource { + GSource parent_source; + VEvent *pending_event; +}; +typedef struct _SmartcardSource SmartcardSource; + +static gboolean smartcard_source_prepare(GSource *source, gint *timeout) +{ + SmartcardSource *smartcard_source = (SmartcardSource *)source; + + if (smartcard_source->pending_event == NULL) + smartcard_source->pending_event = vevent_get_next_vevent(); + + if (timeout != NULL) + *timeout = -1; + + return (smartcard_source->pending_event != NULL); +} + +static gboolean smartcard_source_check(GSource *source) +{ + return smartcard_source_prepare(source, NULL); +} + +static gboolean smartcard_source_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + SmartcardSource *smartcard_source = (SmartcardSource *)source; + SmartcardSourceFunc smartcard_callback = (SmartcardSourceFunc)callback; + + g_return_val_if_fail(smartcard_source->pending_event != NULL, FALSE); + + if (callback) { + gboolean event_consumed; + event_consumed = smartcard_callback(smartcard_source->pending_event, + user_data); + if (event_consumed) { + vevent_delete(smartcard_source->pending_event); + smartcard_source->pending_event = NULL; + } + } + + return TRUE; +} + +static void smartcard_source_finalize(GSource *source) +{ + SmartcardSource *smartcard_source = (SmartcardSource *)source; + + g_clear_pointer(&smartcard_source->pending_event, vevent_delete); +} + +static GSource *smartcard_monitor_source_new(void) +{ + static GSourceFuncs source_funcs = { + .prepare = smartcard_source_prepare, + .check = smartcard_source_check, + .dispatch = smartcard_source_dispatch, + .finalize = smartcard_source_finalize + }; + GSource *source; + + source = g_source_new(&source_funcs, sizeof(SmartcardSource)); + g_source_set_name(source, "Smartcard event source"); + return source; +} + +static guint smartcard_monitor_add(SmartcardSourceFunc callback, + gpointer user_data) +{ + GSource *source; + guint id; + + source = smartcard_monitor_source_new(); + g_source_set_callback(source, (GSourceFunc)callback, user_data, NULL); + id = g_source_attach(source, NULL); + g_source_unref(source); + + return id; +} + +static void +spice_smartcard_manager_update_monitor(void) +{ + SpiceSmartcardManager *self = spice_smartcard_manager_get(); + SpiceSmartcardManagerPrivate *priv = self->priv; + + if (priv->monitor_id != 0) + return; + + priv->monitor_id = smartcard_monitor_add(smartcard_monitor_dispatch, self); +} + +#define SPICE_SOFTWARE_READER_NAME "Spice Software Smartcard" + +typedef struct { + SpiceSession *session; + GCancellable *cancellable; + GError *err; +} SmartcardManagerInitArgs; + +static gboolean smartcard_manager_init(SmartcardManagerInitArgs *args) +{ + gchar *emul_args = NULL; + VCardEmulOptions *options = NULL; + VCardEmulError emul_init_status; + gchar *dbname = NULL; + GStrv certificates = NULL; + gboolean retval = FALSE; + + SPICE_DEBUG("smartcard_manager_init"); + g_return_val_if_fail(SPICE_IS_SESSION(args->session), FALSE); + g_object_get(G_OBJECT(args->session), + "smartcard-db", &dbname, + "smartcard-certificates", &certificates, + NULL); + + if ((certificates == NULL) || (g_strv_length(certificates) != 3)) + goto init; + + if (dbname) { + emul_args = g_strdup_printf("db=\"%s\" use_hw=no " + "soft=(,%s,CAC,,%s,%s,%s)", + dbname, SPICE_SOFTWARE_READER_NAME, + certificates[0], certificates[1], + certificates[2]); + } else { + emul_args = g_strdup_printf("use_hw=no soft=(,%s,CAC,,%s,%s,%s)", + SPICE_SOFTWARE_READER_NAME, + certificates[0], certificates[1], + certificates[2]); + } + + options = vcard_emul_options(emul_args); + if (options == NULL) { + args->err = g_error_new(SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "vcard_emul_options() failed!"); + goto end; + } + + if (g_cancellable_set_error_if_cancelled(args->cancellable, &args->err)) + goto end; + +init: + SPICE_DEBUG("vcard_emul_init"); + emul_init_status = vcard_emul_init(options); + if ((emul_init_status != VCARD_EMUL_OK) + && (emul_init_status != VCARD_EMUL_INIT_ALREADY_INITED)) { + args->err = g_error_new(SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "Failed to initialize smartcard"); + goto end; + } + + retval = TRUE; + +end: + SPICE_DEBUG("smartcard_manager_init end: %d", retval); + g_free(emul_args); + g_free(dbname); + g_strfreev(certificates); + return retval; +} + +static void smartcard_manager_init_helper(GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) +{ + static GOnce smartcard_manager_once = G_ONCE_INIT; + SmartcardManagerInitArgs args; + + args.session = SPICE_SESSION(object); + args.cancellable = cancellable; + args.err = NULL; + + + g_once(&smartcard_manager_once, + (GThreadFunc)smartcard_manager_init, + &args); + + if (args.err != NULL) + g_task_return_error(task, args.err); + else + g_task_return_boolean(task, TRUE); +} + + +G_GNUC_INTERNAL +void spice_smartcard_manager_init_async(SpiceSession *session, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer opaque) +{ + GTask *task = g_task_new(session, cancellable, callback, opaque); + + g_task_run_in_thread(task, smartcard_manager_init_helper); + g_object_unref(task); +} + +G_GNUC_INTERNAL +gboolean spice_smartcard_manager_init_finish(SpiceSession *session, + GAsyncResult *result, + GError **err) +{ + GTask *task = G_TASK(result); + + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + g_return_val_if_fail(G_IS_TASK(task), FALSE); + + SPICE_DEBUG("smartcard_manager_finish"); + + spice_smartcard_manager_update_monitor(); + + return g_task_propagate_boolean(task, err); +} + +/** + * spice_smartcard_reader_is_software: + * @reader: a #SpiceSmartcardReader + * + * Tests if @reader is a software (emulated) smartcard reader. + * + * Returns: TRUE if @reader is a software (emulated) smartcard reader, + * FALSE otherwise + */ +gboolean spice_smartcard_reader_is_software(SpiceSmartcardReader *reader) +{ + g_return_val_if_fail(reader != NULL, FALSE); + return (strcmp(vreader_get_name((VReader*)reader), SPICE_SOFTWARE_READER_NAME) == 0); +} + +/** + * spice_smartcard_reader_insert_card: + * @reader: a #SpiceSmartcardReader + * + * Simulates insertion of a smartcard in the software smartcard reader + * @reader. If @reader is not a software smartcard reader, FALSE will be + * returned. + * + * Returns: TRUE if insertion of a card was successfully simulated, FALSE + * otherwise + */ +gboolean spice_smartcard_reader_insert_card(SpiceSmartcardReader *reader) +{ + VCardEmulError status; + + g_return_val_if_fail(spice_smartcard_reader_is_software(reader), FALSE); + + status = vcard_emul_force_card_insert((VReader *)reader); + + return (status == VCARD_EMUL_OK); +} + +/** + * spice_smartcard_reader_remove_card: + * @reader: a #SpiceSmartcardReader + * + * Simulates removal of a smartcard from the software smartcard reader + * @reader. If @reader is not a software smartcard reader, FALSE will be + * returned. + * + * Returns: TRUE if removal of a card was successfully simulated, FALSE + * otherwise + */ +gboolean spice_smartcard_reader_remove_card(SpiceSmartcardReader *reader) +{ + VCardEmulError status; + + g_return_val_if_fail(spice_smartcard_reader_is_software(reader), FALSE); + + status = vcard_emul_force_card_remove((VReader *)reader); + + return (status == VCARD_EMUL_OK); +} + +/** + * spice_smartcard_manager_get_readers: + * @manager: a #SpiceSmartcardManager + * + * Gets the list of smartcard readers that are currently available, they + * can be either software (emulated) readers, or hardware ones. + * + * Returns: (element-type SpiceSmartcardReader) (transfer full): a newly + * allocated list of SpiceSmartcardReader instances, or NULL if none were + * found. When no longer needed, the list must be freed after unreferencing + * its elements with g_boxed_free() + * + * Since: 0.20 + */ +GList *spice_smartcard_manager_get_readers(SpiceSmartcardManager *manager) +{ + + GList *readers = NULL; + VReaderList *vreader_list; + VReaderListEntry *entry; + + vreader_list = vreader_get_reader_list(); + + if (vreader_list == NULL) + return NULL; + + for (entry = vreader_list_get_first(vreader_list); + entry != NULL; + entry = vreader_list_get_next(entry)) { + VReader *reader; + + reader = vreader_list_get_reader(entry); + g_warn_if_fail(reader != NULL); + readers = g_list_prepend(readers, vreader_reference(reader)); + } + vreader_list_delete(vreader_list); + + return g_list_reverse(readers); +} + +/** + * spice_smartcard_manager_insert_card: + * @manager: a #SpiceSmartcardManager + * + * Simulates the insertion of a smartcard in the guest. Valid certificates + * must have been set in #SpiceSession:smartcard-certificates for software + * smartcard support to work. At the moment, only one software smartcard + * reader is supported, that's why there is no parameter to indicate which + * reader to insert the card in. + * + * Returns: TRUE if smartcard insertion was successfully simulated, FALSE + * if this failed, or if software smartcard support isn't enabled. + * + * Since: 0.20 + */ +gboolean spice_smartcard_manager_insert_card(SpiceSmartcardManager *manager) +{ + SpiceSmartcardReader *reader; + + g_return_val_if_fail (manager->priv->software_reader != NULL, FALSE); + + reader = (SpiceSmartcardReader *)manager->priv->software_reader; + + return spice_smartcard_reader_insert_card(reader); +} + +/** + * spice_smartcard_manager_remove_card: + * @manager: a #SpiceSmartcardManager + * + * Simulates the removal of a smartcard in the guest. At the moment, only + * one software smartcard reader is supported, that's why there is no + * parameter to indicate which reader to insert the card in. + * + * Returns: TRUE if smartcard removal was successfully simulated, FALSE + * if this failed, or if software smartcard support isn't enabled. + * + * Since: 0.20 + */ +gboolean spice_smartcard_manager_remove_card(SpiceSmartcardManager *manager) +{ + SpiceSmartcardReader *reader; + + g_return_val_if_fail (manager->priv->software_reader != NULL, FALSE); + + reader = (SpiceSmartcardReader *)manager->priv->software_reader; + + return spice_smartcard_reader_remove_card(reader); +} +#else +gboolean spice_smartcard_reader_is_software(SpiceSmartcardReader *reader) +{ + return TRUE; +} + +G_GNUC_INTERNAL +void spice_smartcard_manager_init_async(SpiceSession *session, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer opaque) +{ + SPICE_DEBUG("using fake smartcard backend"); +} + +G_GNUC_INTERNAL +gboolean spice_smartcard_manager_init_finish(SpiceSession *session, + GAsyncResult *result, + GError **err) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + return TRUE; +} + +gboolean spice_smartcard_manager_insert_card(SpiceSmartcardManager *manager) +{ + return FALSE; +} + +gboolean spice_smartcard_manager_remove_card(SpiceSmartcardManager *manager) +{ + return FALSE; +} + +gboolean spice_smartcard_reader_insert_card(SpiceSmartcardReader *reader) +{ + return FALSE; +} + +gboolean spice_smartcard_reader_remove_card(SpiceSmartcardReader *reader) +{ + return FALSE; +} + +GList *spice_smartcard_manager_get_readers(SpiceSmartcardManager *manager) +{ + return NULL; +} + +#endif /* USE_SMARTCARD */ diff --git a/src/smartcard-manager.h b/src/smartcard-manager.h new file mode 100644 index 0000000..e4a6277 --- /dev/null +++ b/src/smartcard-manager.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_SMARTCARD_MANAGER_H__ +#define __SPICE_SMARTCARD_MANAGER_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-types.h" +#include "spice-util.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_SMARTCARD_MANAGER (spice_smartcard_manager_get_type ()) +#define SPICE_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_SMARTCARD_MANAGER, SpiceSmartcardManager)) +#define SPICE_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_SMARTCARD_MANAGER, SpiceSmartcardManagerClass)) +#define SPICE_IS_SMARTCARD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_SMARTCARD_MANAGER)) +#define SPICE_IS_SMARTCARD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_SMARTCARD_MANAGER)) +#define SPICE_SMARTCARD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_SMARTCARD_MANAGER, SpiceSmartcardManagerClass)) + +#define SPICE_TYPE_SMARTCARD_READER (spice_smartcard_reader_get_type()) + +typedef struct _SpiceSmartcardManager SpiceSmartcardManager; +typedef struct _SpiceSmartcardManagerClass SpiceSmartcardManagerClass; +typedef struct _SpiceSmartcardManagerPrivate SpiceSmartcardManagerPrivate; + +/** + * SpiceSmartcardReader: + * + * The #SpiceSmartcardReader struct is opaque and cannot be accessed directly. + */ +typedef struct _SpiceSmartcardReader SpiceSmartcardReader; + +/** + * SpiceSmartcardManager: + * + * The #SpiceSmartcardManager struct is opaque and should not be accessed directly. + */ +struct _SpiceSmartcardManager +{ + GObject parent; + + /*< private >*/ + SpiceSmartcardManagerPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceSmartcardManagerClass: + * @parent_class: Parent class. + * @reader_added: Signal class handler for the #SpiceSmartcardManager::reader_added signal. + * @reader_removed: Signal class handler for the #SpiceSmartcardManager::reader_removed signal. + * @card_inserted: Signal class handler for the #SpiceSmartcardManager::card_inserted signal. + * @card_removed: Signal class handler for the #SpiceSmartcardManager::card_removed signal. + * + * Class structure for #SpiceSmartcardManager. + */ +struct _SpiceSmartcardManagerClass +{ + GObjectClass parent_class; + /*< public >*/ + /* signals */ + void (*reader_added)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader); + void (*reader_removed)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader); + void (*card_inserted)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader); + void (*card_removed)(SpiceSmartcardManager *manager, SpiceSmartcardReader *reader ); + + /*< private >*/ + /* + * If adding fields to this struct, remove corresponding + * amount of padding to avoid changing overall struct size + */ + gchar _spice_reserved[SPICE_RESERVED_PADDING]; +}; + +GType spice_smartcard_manager_get_type(void); +GType spice_smartcard_reader_get_type(void); + +SpiceSmartcardManager *spice_smartcard_manager_get(void); +gboolean spice_smartcard_manager_insert_card(SpiceSmartcardManager *manager); +gboolean spice_smartcard_manager_remove_card(SpiceSmartcardManager *manager); +gboolean spice_smartcard_reader_is_software(SpiceSmartcardReader *reader); +gboolean spice_smartcard_reader_insert_card(SpiceSmartcardReader *reader); +gboolean spice_smartcard_reader_remove_card(SpiceSmartcardReader *reader); +GList *spice_smartcard_manager_get_readers(SpiceSmartcardManager *manager); + +G_END_DECLS + +#endif /* __SPICE_SMARTCARD_MANAGER_H__ */ diff --git a/src/spice-audio-priv.h b/src/spice-audio-priv.h new file mode 100644 index 0000000..f108059 --- /dev/null +++ b/src/spice-audio-priv.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_AUDIO_PRIVATE_H__ +#define __SPICE_AUDIO_PRIVATE_H__ + +#include +#include +#include "spice-session.h" + +G_BEGIN_DECLS + +struct _SpiceAudioPrivate { + SpiceSession *session; + GMainContext *main_context; +}; + +void spice_audio_get_playback_volume_info_async(SpiceAudio *audio, GCancellable *cancellable, + SpiceMainChannel *main_channel, GAsyncReadyCallback callback, gpointer user_data); +gboolean spice_audio_get_playback_volume_info_finish(SpiceAudio *audio, GAsyncResult *res, + gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); +void spice_audio_get_record_volume_info_async(SpiceAudio *audio, GCancellable *cancellable, + SpiceMainChannel *main_channel, GAsyncReadyCallback callback, gpointer user_data); +gboolean spice_audio_get_record_volume_info_finish(SpiceAudio *audio, GAsyncResult *res, + gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); +G_END_DECLS + +#endif /* __SPICE_AUDIO_PRIVATE_H__ */ diff --git a/src/spice-audio.c b/src/spice-audio.c new file mode 100644 index 0000000..c514d30 --- /dev/null +++ b/src/spice-audio.c @@ -0,0 +1,274 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +/* + * simple audio init dispatcher + */ + +/** + * SECTION:spice-audio + * @short_description: a helper to play and to record audio channels + * @title: Spice Audio + * @section_id: + * @see_also: #SpiceRecordChannel, and #SpicePlaybackChannel + * @stability: Stable + * @include: spice-client.h + * + * A class that handles the playback and record channels for your + * application, and connect them to the default sound system. + */ + +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-audio.h" +#include "spice-session-priv.h" +#include "spice-channel-priv.h" +#include "spice-audio-priv.h" + +#ifdef HAVE_PULSE +#include "spice-pulse.h" +#endif +#ifdef HAVE_GSTAUDIO +#include "spice-gstaudio.h" +#endif + +#define SPICE_AUDIO_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_AUDIO, SpiceAudioPrivate)) + +G_DEFINE_ABSTRACT_TYPE(SpiceAudio, spice_audio, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_SESSION, + PROP_MAIN_CONTEXT, +}; + +static void spice_audio_finalize(GObject *gobject) +{ + SpiceAudio *self = SPICE_AUDIO(gobject); + SpiceAudioPrivate *priv = self->priv; + + g_clear_pointer(&priv->main_context, g_main_context_unref); + + if (G_OBJECT_CLASS(spice_audio_parent_class)->finalize) + G_OBJECT_CLASS(spice_audio_parent_class)->finalize(gobject); +} + +static void spice_audio_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceAudio *self = SPICE_AUDIO(gobject); + SpiceAudioPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, priv->session); + break; + case PROP_MAIN_CONTEXT: + g_value_set_boxed(value, priv->main_context); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_audio_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceAudio *self = SPICE_AUDIO(gobject); + SpiceAudioPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + priv->session = g_value_get_object(value); + break; + case PROP_MAIN_CONTEXT: + priv->main_context = g_value_dup_boxed(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_audio_class_init(SpiceAudioClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->finalize = spice_audio_finalize; + gobject_class->get_property = spice_audio_get_property; + gobject_class->set_property = spice_audio_set_property; + + /** + * SpiceAudio:session: + * + * #SpiceSession this #SpiceAudio is associated with + * + **/ + pspec = g_param_spec_object("session", "Session", "SpiceSession", + SPICE_TYPE_SESSION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_SESSION, pspec); + + /** + * SpiceAudio:main-context: + */ + pspec = g_param_spec_boxed("main-context", "Main Context", + "GMainContext to use for the event source", + G_TYPE_MAIN_CONTEXT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_MAIN_CONTEXT, pspec); + + g_type_class_add_private(klass, sizeof(SpiceAudioPrivate)); +} + +static void spice_audio_init(SpiceAudio *self) +{ + self->priv = SPICE_AUDIO_GET_PRIVATE(self); +} + +static void connect_channel(SpiceAudio *self, SpiceChannel *channel) +{ + if (channel->priv->state != SPICE_CHANNEL_STATE_UNCONNECTED) + return; + + if (SPICE_AUDIO_GET_CLASS(self)->connect_channel(self, channel)) + spice_channel_connect(channel); +} + +static void update_audio_channels(SpiceAudio *self, SpiceSession *session) +{ + GList *list, *tmp; + + if (!spice_session_get_audio_enabled(session)) { + SPICE_DEBUG("FIXME: disconnect audio channels"); + return; + } + + list = spice_session_get_channels(session); + for (tmp = g_list_first(list); tmp != NULL; tmp = g_list_next(tmp)) { + connect_channel(self, tmp->data); + } + g_list_free(list); +} + +static void channel_new(SpiceSession *session, SpiceChannel *channel, SpiceAudio *self) +{ + connect_channel(self, channel); +} + +static void session_enable_audio(GObject *gobject, GParamSpec *pspec, + gpointer user_data) +{ + update_audio_channels(SPICE_AUDIO(user_data), SPICE_SESSION(gobject)); +} + +void spice_audio_get_playback_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(audio != NULL); + SPICE_AUDIO_GET_CLASS(audio)->get_playback_volume_info_async(audio, + cancellable, main_channel, callback, user_data); +} + +gboolean spice_audio_get_playback_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + g_return_val_if_fail(audio != NULL, FALSE); + return SPICE_AUDIO_GET_CLASS(audio)->get_playback_volume_info_finish(audio, + res, mute, nchannels, volume, error); +} + +void spice_audio_get_record_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(audio != NULL); + SPICE_AUDIO_GET_CLASS(audio)->get_record_volume_info_async(audio, + cancellable, main_channel, callback, user_data); +} + +gboolean spice_audio_get_record_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + g_return_val_if_fail(audio != NULL, FALSE); + return SPICE_AUDIO_GET_CLASS(audio)->get_record_volume_info_finish(audio, + res, mute, nchannels, volume, error); +} + +/** + * spice_audio_new: + * @session: the #SpiceSession to connect to + * @context: (allow-none): a #GMainContext to attach to (or %NULL for + * default). + * @name: (allow-none): a name for the audio channels (or %NULL for + * application name). + * + * Once instantiated, #SpiceAudio will handle the playback and record + * channels to stream to your local audio system. + * + * Returns: a new #SpiceAudio instance or %NULL if no backend or failed. + * Deprecated: 0.8: Use spice_audio_get() instead + **/ +SpiceAudio *spice_audio_new(SpiceSession *session, GMainContext *context, + const char *name) +{ + SpiceAudio *self = NULL; + + if (context == NULL) + context = g_main_context_default(); + if (name == NULL) + name = g_get_application_name(); + +#ifdef HAVE_PULSE + self = SPICE_AUDIO(spice_pulse_new(session, context, name)); +#endif +#ifdef HAVE_GSTAUDIO + if (!self) + self = SPICE_AUDIO(spice_gstaudio_new(session, context, name)); +#endif + if (!self) + return NULL; + + spice_g_signal_connect_object(session, "notify::enable-audio", G_CALLBACK(session_enable_audio), self, 0); + spice_g_signal_connect_object(session, "channel-new", G_CALLBACK(channel_new), self, G_CONNECT_AFTER); + update_audio_channels(self, session); + + return self; +} diff --git a/src/spice-audio.h b/src/spice-audio.h new file mode 100644 index 0000000..01f564a --- /dev/null +++ b/src/spice-audio.h @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_AUDIO_H__ +#define __SPICE_CLIENT_AUDIO_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include +#include "spice-util.h" +#include "spice-session.h" +#include "channel-main.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_AUDIO spice_audio_get_type() + +#define SPICE_AUDIO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_AUDIO, SpiceAudio)) + +#define SPICE_AUDIO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_AUDIO, SpiceAudioClass)) + +#define SPICE_IS_AUDIO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_AUDIO)) + +#define SPICE_IS_AUDIO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_AUDIO)) + +#define SPICE_AUDIO_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_AUDIO, SpiceAudioClass)) + +typedef struct _SpiceAudio SpiceAudio; +typedef struct _SpiceAudioClass SpiceAudioClass; +typedef struct _SpiceAudioPrivate SpiceAudioPrivate; + +/** + * SpiceAudio: + * + * The #SpiceAudio struct is opaque and should not be accessed directly. + */ +struct _SpiceAudio { + GObject parent; + + SpiceAudioPrivate *priv; +}; + +/** + * SpiceAudioClass: + * @parent_class: Parent class. + * + * Class structure for #SpiceAudio. + */ +struct _SpiceAudioClass { + GObjectClass parent_class; + + /*< private >*/ + gboolean (*connect_channel)(SpiceAudio *audio, SpiceChannel *channel); + void (*get_playback_volume_info_async)(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*get_playback_volume_info_finish)(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error); + void (*get_record_volume_info_async)(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*get_record_volume_info_finish)(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error); + + gchar _spice_reserved[SPICE_RESERVED_PADDING - 4 * sizeof(void *)]; +}; + +GType spice_audio_get_type(void); + +SpiceAudio* spice_audio_get(SpiceSession *session, GMainContext *context); + +#ifndef SPICE_DISABLE_DEPRECATED +SPICE_DEPRECATED_FOR(spice_audio_get) +SpiceAudio* spice_audio_new(SpiceSession *session, GMainContext *context, const char *name); +#endif + +G_END_DECLS + +#endif /* __SPICE_CLIENT_AUDIO_H__ */ diff --git a/src/spice-channel-cache.h b/src/spice-channel-cache.h new file mode 100644 index 0000000..75cc2cd --- /dev/null +++ b/src/spice-channel-cache.h @@ -0,0 +1,139 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICE_CHANNEL_CACHE_H_ +# define SPICE_CHANNEL_CACHE_H_ + +#include /* For PRIx64 */ +#include "common/mem.h" +#include "common/ring.h" + +G_BEGIN_DECLS + +typedef struct display_cache_item { + guint64 id; + gboolean lossy; + guint32 ref_count; +} display_cache_item; + +typedef struct display_cache { + GHashTable *table; + gboolean ref_counted; +}display_cache; + +static inline display_cache_item* cache_item_new(guint64 id, gboolean lossy) +{ + display_cache_item *self = g_new(display_cache_item, 1); + self->id = id; + self->lossy = lossy; + self->ref_count = 1; + return self; +} + +static inline void cache_item_free(display_cache_item *self) +{ + g_free(self); +} + +static inline display_cache* cache_new(GDestroyNotify value_destroy) +{ + display_cache * self = g_new(display_cache, 1); + self->table = g_hash_table_new_full(g_int64_hash, g_int64_equal, + (GDestroyNotify) cache_item_free, + value_destroy); + self->ref_counted = FALSE; + return self; +} + +static inline display_cache * cache_image_new(GDestroyNotify value_destroy) +{ + display_cache * self = cache_new(value_destroy); + self->ref_counted = TRUE; + return self; +}; + +static inline gpointer cache_find(display_cache *cache, uint64_t id) +{ + return g_hash_table_lookup(cache->table, &id); +} + +static inline gpointer cache_find_lossy(display_cache *cache, uint64_t id, gboolean *lossy) +{ + gpointer value; + display_cache_item *item; + + if (!g_hash_table_lookup_extended(cache->table, &id, (gpointer*)&item, &value)) + return NULL; + + *lossy = item->lossy; + + return value; +} + +static inline void cache_add_lossy(display_cache *cache, uint64_t id, + gpointer value, gboolean lossy) +{ + display_cache_item *item = cache_item_new(id, lossy); + display_cache_item *current_item; + gpointer current_image; + + //If image is currently in the table add its reference count before replacing it + if(cache->ref_counted) { + if(g_hash_table_lookup_extended(cache->table, &id, (gpointer*) ¤t_item, + (gpointer*) ¤t_image)) { + item->ref_count = current_item->ref_count + 1; + } + } + g_hash_table_replace(cache->table, item, value); +} + +static inline void cache_add(display_cache *cache, uint64_t id, gpointer value) +{ + cache_add_lossy(cache, id, value, FALSE); +} + +static inline gboolean cache_remove(display_cache *cache, uint64_t id) +{ + display_cache_item * item; + gpointer value; + + if( g_hash_table_lookup_extended(cache->table, &id, (gpointer*) &item, &value)) { + --item->ref_count; + if(!cache->ref_counted || item->ref_count == 0 ) { + return g_hash_table_remove(cache->table, &id); + } + } + else { + return FALSE; + } + return TRUE; +} + +static inline void cache_clear(display_cache *cache) +{ + g_hash_table_remove_all(cache->table); +} + +static inline void cache_free(display_cache *cache) +{ + g_hash_table_unref(cache->table); + g_free(cache); +} + +G_END_DECLS + +#endif // SPICE_CHANNEL_CACHE_H_ diff --git a/src/spice-channel-enums.h b/src/spice-channel-enums.h new file mode 100644 index 0000000..02df762 --- /dev/null +++ b/src/spice-channel-enums.h @@ -0,0 +1,7 @@ +#ifndef SPICE_CHANNEL_ENUMS_H +#define SPICE_CHANNEL_ENUMS_H + +#warning "deprecated: please include spice-glib-enums.h" +#include "spice-glib-enums.h" + +#endif /* SPICE_CHANNEL_ENUMS_H */ diff --git a/src/spice-channel-priv.h b/src/spice-channel-priv.h new file mode 100644 index 0000000..50aca5c --- /dev/null +++ b/src/spice-channel-priv.h @@ -0,0 +1,214 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_CHANNEL_PRIV_H__ +#define __SPICE_CLIENT_CHANNEL_PRIV_H__ + +#include "config.h" + +#include +#include + +#if HAVE_SASL +#include +#endif + +#include "spice-channel.h" +#include "spice-util-priv.h" +#include "coroutine.h" +#include "gio-coroutine.h" + +#include "common/client_marshallers.h" +#include "common/client_demarshallers.h" +#include "common/ssl_verify.h" + +G_BEGIN_DECLS + +#define MAX_SPICE_DATA_HEADER_SIZE sizeof(SpiceDataHeader) + +#define CHANNEL_DEBUG(channel, fmt, ...) \ + SPICE_DEBUG("%s: " fmt, SPICE_CHANNEL(channel)->priv->name, ## __VA_ARGS__) + +struct _SpiceMsgOut { + int refcount; + SpiceChannel *channel; + SpiceMessageMarshallers *marshallers; + SpiceMarshaller *marshaller; + uint8_t *header; + gboolean ro_check; +}; + +struct _SpiceMsgIn { + int refcount; + SpiceChannel *channel; + uint8_t header[MAX_SPICE_DATA_HEADER_SIZE]; + uint8_t *data; + int dpos; + uint8_t *parsed; + size_t psize; + message_destructor_t pfree; + SpiceMsgIn *parent; +}; + +enum spice_channel_state { + SPICE_CHANNEL_STATE_UNCONNECTED = 0, + SPICE_CHANNEL_STATE_RECONNECTING, + SPICE_CHANNEL_STATE_CONNECTING, + SPICE_CHANNEL_STATE_READY, + SPICE_CHANNEL_STATE_SWITCHING, + SPICE_CHANNEL_STATE_MIGRATING, + SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE, +}; + +struct _SpiceChannelClassPrivate +{ + GArray *handlers; +}; + +struct _SpiceChannelPrivate { + /* swapped on migration */ + SSL_CTX *ctx; + SSL *ssl; + SpiceOpenSSLVerify *sslverify; + GSocket *sock; + GSocketConnection *conn; + GInputStream *in; + GOutputStream *out; + +#if HAVE_SASL + sasl_conn_t *sasl_conn; + const char *sasl_decoded; + unsigned int sasl_decoded_length; + unsigned int sasl_decoded_offset; +#endif + + gboolean use_mini_header; + uint64_t out_serial; + uint64_t in_serial; + + /* not swapped */ + SpiceSession *session; + GCoroutine coroutine; + int fd; + gboolean has_error; + guint connect_delayed_id; + + GQueue xmit_queue; + gboolean xmit_queue_blocked; + GMutex xmit_queue_lock; + guint xmit_queue_wakeup_id; + guint64 xmit_queue_size; + + char name[16]; + enum spice_channel_state state; + SpiceChannelEvent event; + + spice_parse_channel_func_t parser; + SpiceMessageMarshallers *marshallers; + guint channel_watch; + int tls; + + int channel_id; + int channel_type; + SpiceLinkHeader link_hdr; + SpiceLinkMess link_msg; + SpiceLinkHeader peer_hdr; + SpiceLinkReply* peer_msg; + int peer_pos; + + int message_ack_window; + int message_ack_count; + + GArray *caps; + GArray *common_caps; + GArray *remote_caps; + GArray *remote_common_caps; + + gsize total_read_bytes; + uint64_t last_message_serial; + GSList *flushing; + + gboolean disable_channel_msg; + gboolean auth_needs_username; + gboolean auth_needs_password; + GError *error; +}; + +SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel); +SpiceMsgIn *spice_msg_in_sub_new(SpiceChannel *channel, SpiceMsgIn *parent, + SpiceSubMessage *sub); +void spice_msg_in_ref(SpiceMsgIn *in); +void spice_msg_in_unref(SpiceMsgIn *in); +int spice_msg_in_type(SpiceMsgIn *in); +void *spice_msg_in_parsed(SpiceMsgIn *in); +void *spice_msg_in_raw(SpiceMsgIn *in, int *len); +void spice_msg_in_hexdump(SpiceMsgIn *in); + +SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int type); +void spice_msg_out_ref(SpiceMsgOut *out); +void spice_msg_out_unref(SpiceMsgOut *out); +void spice_msg_out_send(SpiceMsgOut *out); +void spice_msg_out_send_internal(SpiceMsgOut *out); +void spice_msg_out_hexdump(SpiceMsgOut *out, unsigned char *data, int len); + +uint16_t spice_header_get_msg_type(uint8_t *header, gboolean is_mini_header); +uint32_t spice_header_get_msg_size(uint8_t *header, gboolean is_mini_header); + +void spice_channel_up(SpiceChannel *channel); +void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel); + +SpiceSession* spice_channel_get_session(SpiceChannel *channel); +enum spice_channel_state spice_channel_get_state(SpiceChannel *channel); +guint64 spice_channel_get_queue_size (SpiceChannel *channel); + +/* coroutine context */ +typedef void (*handler_msg_in)(SpiceChannel *channel, SpiceMsgIn *msg, gpointer data); +void spice_channel_recv_msg(SpiceChannel *channel, handler_msg_in handler, gpointer data); + +/* channel-base.c */ +void spice_channel_set_handlers(SpiceChannelClass *klass, + const spice_msg_handler* handlers, const int n); +void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *in); + +gint spice_channel_get_channel_id(SpiceChannel *channel); +gint spice_channel_get_channel_type(SpiceChannel *channel); +void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap_msgs); +gboolean spice_channel_get_read_only(SpiceChannel *channel); +void spice_channel_reset(SpiceChannel *channel, gboolean migrating); + +void spice_caps_set(GArray *caps, guint32 cap, const gchar *desc); +#define spice_channel_set_common_capability(channel, cap) \ + spice_caps_set(SPICE_CHANNEL(channel)->priv->common_caps, cap, #cap) +#define spice_channel_set_capability(channel, cap) \ + spice_caps_set(SPICE_CHANNEL(channel)->priv->caps, cap, #cap) + +gchar *spice_channel_supported_string(void); + +void spice_vmc_write_async(SpiceChannel *self, + const void *buffer, gsize count, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gssize spice_vmc_write_finish(SpiceChannel *self, + GAsyncResult *result, GError **error); +#ifdef G_OS_UNIX +gint spice_channel_unix_read_fd(SpiceChannel *channel); +#endif + +G_END_DECLS + +#endif /* __SPICE_CLIENT_CHANNEL_PRIV_H__ */ diff --git a/src/spice-channel.c b/src/spice-channel.c new file mode 100644 index 0000000..0eb0e61 --- /dev/null +++ b/src/spice-channel.c @@ -0,0 +1,3085 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" + +#include "spice-channel-priv.h" +#include "spice-session-priv.h" +#include "spice-marshal.h" +#include "bio-gio.h" + +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#include // TCP_NODELAY +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include + +#include "gio-coroutine.h" + +static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg); +static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out); +static void spice_channel_send_link(SpiceChannel *channel); +static void channel_reset(SpiceChannel *channel, gboolean migrating); +static void spice_channel_reset_capabilities(SpiceChannel *channel); +static void spice_channel_send_migration_handshake(SpiceChannel *channel); +static gboolean channel_connect(SpiceChannel *channel, gboolean tls); + +/** + * SECTION:spice-channel + * @short_description: the base channel class + * @title: Spice Channel + * @section_id: + * @see_also: #SpiceSession, #SpiceMainChannel and other channels + * @stability: Stable + * @include: spice-client.h + * + * #SpiceChannel is the base class for the different kind of Spice + * channel connections, such as #SpiceMainChannel, or + * #SpiceInputsChannel. + */ + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_CHANNEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_CHANNEL, SpiceChannelPrivate)) + +G_DEFINE_TYPE_WITH_CODE (SpiceChannel, spice_channel, G_TYPE_OBJECT, + g_type_add_class_private (g_define_type_id, sizeof (SpiceChannelClassPrivate))); + +/* Properties */ +enum { + PROP_0, + PROP_SESSION, + PROP_CHANNEL_TYPE, + PROP_CHANNEL_ID, + PROP_TOTAL_READ_BYTES, +}; + +/* Signals */ +enum { + SPICE_CHANNEL_EVENT, + SPICE_CHANNEL_OPEN_FD, + + SPICE_CHANNEL_LAST_SIGNAL, +}; + +static guint signals[SPICE_CHANNEL_LAST_SIGNAL]; + +static void spice_channel_iterate_write(SpiceChannel *channel); +static void spice_channel_iterate_read(SpiceChannel *channel); + +static void spice_channel_init(SpiceChannel *channel) +{ + SpiceChannelPrivate *c; + + c = channel->priv = SPICE_CHANNEL_GET_PRIVATE(channel); + + c->out_serial = 1; + c->in_serial = 1; + c->fd = -1; + c->auth_needs_username = FALSE; + c->auth_needs_password = FALSE; + strcpy(c->name, "?"); + c->caps = g_array_new(FALSE, TRUE, sizeof(guint32)); + c->common_caps = g_array_new(FALSE, TRUE, sizeof(guint32)); + c->remote_caps = g_array_new(FALSE, TRUE, sizeof(guint32)); + c->remote_common_caps = g_array_new(FALSE, TRUE, sizeof(guint32)); + spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION); + spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_MINI_HEADER); +#ifdef HAVE_SASL + spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_AUTH_SASL); +#endif + g_queue_init(&c->xmit_queue); + g_mutex_init(&c->xmit_queue_lock); +} + +static void spice_channel_constructed(GObject *gobject) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + SpiceChannelPrivate *c = channel->priv; + const char *desc = spice_channel_type_to_string(c->channel_type); + + snprintf(c->name, sizeof(c->name), "%s-%d:%d", + desc, c->channel_type, c->channel_id); + CHANNEL_DEBUG(channel, "%s", __FUNCTION__); + + const char *disabled = g_getenv("SPICE_DISABLE_CHANNELS"); + if (disabled && strstr(disabled, desc)) + c->disable_channel_msg = TRUE; + + spice_session_channel_new(c->session, channel); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_channel_parent_class)->constructed) + G_OBJECT_CLASS(spice_channel_parent_class)->constructed(gobject); +} + +static void spice_channel_dispose(GObject *gobject) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + SpiceChannelPrivate *c = channel->priv; + + CHANNEL_DEBUG(channel, "%s %p", __FUNCTION__, gobject); + + spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED); + + g_clear_object(&c->session); + + g_clear_error(&c->error); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_channel_parent_class)->dispose) + G_OBJECT_CLASS(spice_channel_parent_class)->dispose(gobject); +} + +static void spice_channel_finalize(GObject *gobject) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + SpiceChannelPrivate *c = channel->priv; + + CHANNEL_DEBUG(channel, "%s %p", __FUNCTION__, gobject); + + g_idle_remove_by_data(gobject); + + g_mutex_clear(&c->xmit_queue_lock); + + if (c->caps) + g_array_free(c->caps, TRUE); + + if (c->common_caps) + g_array_free(c->common_caps, TRUE); + + if (c->remote_caps) + g_array_free(c->remote_caps, TRUE); + + if (c->remote_common_caps) + g_array_free(c->remote_common_caps, TRUE); + + g_clear_pointer(&c->peer_msg, g_free); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_channel_parent_class)->finalize(gobject); +} + +static void spice_channel_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + SpiceChannelPrivate *c = channel->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, c->session); + break; + case PROP_CHANNEL_TYPE: + g_value_set_int(value, c->channel_type); + break; + case PROP_CHANNEL_ID: + g_value_set_int(value, c->channel_id); + break; + case PROP_TOTAL_READ_BYTES: + g_value_set_ulong(value, c->total_read_bytes); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +G_GNUC_INTERNAL +gint spice_channel_get_channel_id(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + g_return_val_if_fail(c != NULL, 0); + return c->channel_id; +} + +G_GNUC_INTERNAL +gint spice_channel_get_channel_type(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + g_return_val_if_fail(c != NULL, 0); + return c->channel_type; +} + +static void spice_channel_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + SpiceChannelPrivate *c = channel->priv; + + switch (prop_id) { + case PROP_SESSION: + c->session = g_value_dup_object(value); + break; + case PROP_CHANNEL_TYPE: + c->channel_type = g_value_get_int(value); + break; + case PROP_CHANNEL_ID: + c->channel_id = g_value_get_int(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_channel_class_init(SpiceChannelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->iterate_write = spice_channel_iterate_write; + klass->iterate_read = spice_channel_iterate_read; + klass->channel_reset = channel_reset; + + gobject_class->constructed = spice_channel_constructed; + gobject_class->dispose = spice_channel_dispose; + gobject_class->finalize = spice_channel_finalize; + gobject_class->get_property = spice_channel_get_property; + gobject_class->set_property = spice_channel_set_property; + klass->handle_msg = spice_channel_handle_msg; + + g_object_class_install_property + (gobject_class, PROP_SESSION, + g_param_spec_object("spice-session", + "Spice session", + "Spice session", + SPICE_TYPE_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_CHANNEL_TYPE, + g_param_spec_int("channel-type", + "Channel type", + "Channel type", + -1, INT_MAX, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_CHANNEL_ID, + g_param_spec_int("channel-id", + "Channel ID", + "Channel ID", + -1, INT_MAX, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_TOTAL_READ_BYTES, + g_param_spec_ulong("total-read-bytes", + "Total read bytes", + "Total read bytes", + 0, G_MAXULONG, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceChannel::channel-event: + * @channel: the channel that emitted the signal + * @event: a #SpiceChannelEvent + * + * The #SpiceChannel::channel-event signal is emitted when the + * state of the connection is changed. In case of errors, + * spice_channel_get_error() may provide additional informations + * on the source of the error. + **/ + signals[SPICE_CHANNEL_EVENT] = + g_signal_new("channel-event", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceChannelClass, channel_event), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, + 1, + SPICE_TYPE_CHANNEL_EVENT); + + /** + * SpiceChannel::open-fd: + * @channel: the channel that emitted the signal + * @with_tls: wether TLS connection is requested + * + * The #SpiceChannel::open-fd signal is emitted when a new + * connection is requested. This signal is emitted when the + * connection is made with spice_session_open_fd(). + **/ + signals[SPICE_CHANNEL_OPEN_FD] = + g_signal_new("open-fd", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceChannelClass, open_fd), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + + g_type_class_add_private(klass, sizeof(SpiceChannelPrivate)); + + SSL_library_init(); + SSL_load_error_strings(); +} + +/* ---------------------------------------------------------------- */ +/* private header api */ + +static inline void spice_header_set_msg_type(uint8_t *header, gboolean is_mini_header, + uint16_t type) +{ + if (is_mini_header) { + ((SpiceMiniDataHeader *)header)->type = GUINT16_TO_LE(type); + } else { + ((SpiceDataHeader *)header)->type = GUINT16_TO_LE(type); + } +} + +static inline void spice_header_set_msg_size(uint8_t *header, gboolean is_mini_header, + uint32_t size) +{ + if (is_mini_header) { + ((SpiceMiniDataHeader *)header)->size = GUINT32_TO_LE(size); + } else { + ((SpiceDataHeader *)header)->size = GUINT32_TO_LE(size); + } +} + +G_GNUC_INTERNAL +uint16_t spice_header_get_msg_type(uint8_t *header, gboolean is_mini_header) +{ + if (is_mini_header) { + return GUINT16_FROM_LE(((SpiceMiniDataHeader *)header)->type); + } else { + return GUINT16_FROM_LE(((SpiceDataHeader *)header)->type); + } +} + +G_GNUC_INTERNAL +uint32_t spice_header_get_msg_size(uint8_t *header, gboolean is_mini_header) +{ + if (is_mini_header) { + return GUINT32_FROM_LE(((SpiceMiniDataHeader *)header)->size); + } else { + return GUINT32_FROM_LE(((SpiceDataHeader *)header)->size); + } +} + +static inline int spice_header_get_header_size(gboolean is_mini_header) +{ + return is_mini_header ? sizeof(SpiceMiniDataHeader) : sizeof(SpiceDataHeader); +} + +static inline void spice_header_set_msg_serial(uint8_t *header, gboolean is_mini_header, + uint64_t serial) +{ + if (!is_mini_header) { + ((SpiceDataHeader *)header)->serial = GUINT64_TO_LE(serial); + } +} + +static inline void spice_header_reset_msg_sub_list(uint8_t *header, gboolean is_mini_header) +{ + if (!is_mini_header) { + ((SpiceDataHeader *)header)->sub_list = 0; + } +} + +static inline uint64_t spice_header_get_in_msg_serial(SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = in->channel->priv; + uint8_t *header = in->header; + + if (c->use_mini_header) { + return c->in_serial; + } else { + return ((SpiceDataHeader *)header)->serial; + } +} + +static inline uint64_t spice_header_get_out_msg_serial(SpiceMsgOut *out) +{ + SpiceChannelPrivate *c = out->channel->priv; + + if (c->use_mini_header) { + return c->out_serial; + } else { + return ((SpiceDataHeader *)out->header)->serial; + } +} + +static inline uint32_t spice_header_get_msg_sub_list(uint8_t *header, gboolean is_mini_header) +{ + if (is_mini_header) { + return 0; + } else { + return GUINT32_FROM_LE(((SpiceDataHeader *)header)->sub_list); + } +} + +/* ---------------------------------------------------------------- */ +/* private msg api */ + +G_GNUC_INTERNAL +SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel) +{ + SpiceMsgIn *in; + + g_return_val_if_fail(channel != NULL, NULL); + + in = g_new0(SpiceMsgIn, 1); + in->refcount = 1; + in->channel = channel; + + return in; +} + +G_GNUC_INTERNAL +SpiceMsgIn *spice_msg_in_sub_new(SpiceChannel *channel, SpiceMsgIn *parent, + SpiceSubMessage *sub) +{ + SpiceMsgIn *in; + + g_return_val_if_fail(channel != NULL, NULL); + + in = spice_msg_in_new(channel); + spice_header_set_msg_type(in->header, channel->priv->use_mini_header, sub->type); + spice_header_set_msg_size(in->header, channel->priv->use_mini_header, sub->size); + in->data = (uint8_t*)(sub+1); + in->dpos = sub->size; + in->parent = parent; + spice_msg_in_ref(parent); + return in; +} + +G_GNUC_INTERNAL +void spice_msg_in_ref(SpiceMsgIn *in) +{ + g_return_if_fail(in != NULL); + + in->refcount++; +} + +G_GNUC_INTERNAL +void spice_msg_in_unref(SpiceMsgIn *in) +{ + g_return_if_fail(in != NULL); + + in->refcount--; + if (in->refcount > 0) + return; + if (in->parsed) + in->pfree(in->parsed); + if (in->parent) { + spice_msg_in_unref(in->parent); + } else { + g_free(in->data); + } + g_free(in); +} + +G_GNUC_INTERNAL +int spice_msg_in_type(SpiceMsgIn *in) +{ + g_return_val_if_fail(in != NULL, -1); + + return spice_header_get_msg_type(in->header, in->channel->priv->use_mini_header); +} + +G_GNUC_INTERNAL +void *spice_msg_in_parsed(SpiceMsgIn *in) +{ + g_return_val_if_fail(in != NULL, NULL); + + return in->parsed; +} + +G_GNUC_INTERNAL +void *spice_msg_in_raw(SpiceMsgIn *in, int *len) +{ + g_return_val_if_fail(in != NULL, NULL); + g_return_val_if_fail(len != NULL, NULL); + + *len = in->dpos; + return in->data; +} + +static void hexdump(const char *prefix, unsigned char *data, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) + fprintf(stderr, "%s:", prefix); + if (i % 4 == 0) + fprintf(stderr, " "); + fprintf(stderr, " %02x", data[i]); + if (i % 16 == 15) + fprintf(stderr, "\n"); + } + if (i % 16 != 0) + fprintf(stderr, "\n"); +} + +G_GNUC_INTERNAL +void spice_msg_in_hexdump(SpiceMsgIn *in) +{ + SpiceChannelPrivate *c = in->channel->priv; + + fprintf(stderr, "--\n<< hdr: %s serial %" PRIu64 " type %u size %u sub-list %u\n", + c->name, spice_header_get_in_msg_serial(in), + spice_header_get_msg_type(in->header, c->use_mini_header), + spice_header_get_msg_size(in->header, c->use_mini_header), + spice_header_get_msg_sub_list(in->header, c->use_mini_header)); + hexdump("<< msg", in->data, in->dpos); +} + +G_GNUC_INTERNAL +void spice_msg_out_hexdump(SpiceMsgOut *out, unsigned char *data, int len) +{ + SpiceChannelPrivate *c = out->channel->priv; + + fprintf(stderr, "--\n>> hdr: %s serial %" PRIu64 " type %u size %u sub-list %u\n", + c->name, + spice_header_get_out_msg_serial(out), + spice_header_get_msg_type(out->header, c->use_mini_header), + spice_header_get_msg_size(out->header, c->use_mini_header), + spice_header_get_msg_sub_list(out->header, c->use_mini_header)); + hexdump(">> msg", data, len); +} + +static gboolean msg_check_read_only (int channel_type, int msg_type) +{ + if (msg_type < 100) // those are the common messages + return FALSE; + + switch (channel_type) { + /* messages allowed to be sent in read-only mode */ + case SPICE_CHANNEL_MAIN: + switch (msg_type) { + case SPICE_MSGC_MAIN_CLIENT_INFO: + case SPICE_MSGC_MAIN_MIGRATE_CONNECTED: + case SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR: + case SPICE_MSGC_MAIN_ATTACH_CHANNELS: + case SPICE_MSGC_MAIN_MIGRATE_END: + return FALSE; + } + break; + case SPICE_CHANNEL_DISPLAY: + return FALSE; + } + + return TRUE; +} + +G_GNUC_INTERNAL +SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int type) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + + g_return_val_if_fail(c != NULL, NULL); + + out = g_new0(SpiceMsgOut, 1); + out->refcount = 1; + out->channel = channel; + out->ro_check = msg_check_read_only(c->channel_type, type); + + out->marshallers = c->marshallers; + out->marshaller = spice_marshaller_new(); + + out->header = spice_marshaller_reserve_space(out->marshaller, + spice_header_get_header_size(c->use_mini_header)); + spice_marshaller_set_base(out->marshaller, spice_header_get_header_size(c->use_mini_header)); + spice_header_set_msg_type(out->header, c->use_mini_header, type); + spice_header_set_msg_serial(out->header, c->use_mini_header, c->out_serial); + spice_header_reset_msg_sub_list(out->header, c->use_mini_header); + + c->out_serial++; + return out; +} + +G_GNUC_INTERNAL +void spice_msg_out_ref(SpiceMsgOut *out) +{ + g_return_if_fail(out != NULL); + + out->refcount++; +} + +G_GNUC_INTERNAL +void spice_msg_out_unref(SpiceMsgOut *out) +{ + g_return_if_fail(out != NULL); + + out->refcount--; + if (out->refcount > 0) + return; + spice_marshaller_destroy(out->marshaller); + g_free(out); +} + +/* system context */ +static gboolean spice_channel_idle_wakeup(gpointer user_data) +{ + SpiceChannel *channel = SPICE_CHANNEL(user_data); + SpiceChannelPrivate *c = channel->priv; + + /* + * Note: + * + * - This must be done before the wakeup as that may eventually + * call channel_reset() which checks this. + * - The lock calls are really necessary, this fixes the following race: + * 1) usb-event-thread calls spice_msg_out_send() + * 2) spice_msg_out_send calls g_timeout_add_full(...) + * 3) we run, set xmit_queue_wakeup_id to 0 + * 4) spice_msg_out_send stores the result of g_timeout_add_full() in + * xmit_queue_wakeup_id, overwriting the 0 we just stored + * 5) xmit_queue_wakeup_id now says there is a wakeup pending which is + * false + */ + g_mutex_lock(&c->xmit_queue_lock); + c->xmit_queue_wakeup_id = 0; + g_mutex_unlock(&c->xmit_queue_lock); + + spice_channel_wakeup(channel, FALSE); + + return FALSE; +} + +/* any context (system/co-routine/usb-event-thread) */ +G_GNUC_INTERNAL +void spice_msg_out_send(SpiceMsgOut *out) +{ + SpiceChannelPrivate *c; + gboolean was_empty; + guint32 size; + + g_return_if_fail(out != NULL); + g_return_if_fail(out->channel != NULL); + c = out->channel->priv; + size = spice_marshaller_get_total_size(out->marshaller); + + g_mutex_lock(&c->xmit_queue_lock); + if (c->xmit_queue_blocked) { + g_warning("message queue is blocked, dropping message"); + goto end; + } + + was_empty = g_queue_is_empty(&c->xmit_queue); + g_queue_push_tail(&c->xmit_queue, out); + c->xmit_queue_size = (was_empty) ? size : c->xmit_queue_size + size; + + /* One wakeup is enough to empty the entire queue -> only do a wakeup + if the queue was empty, and there isn't one pending already. */ + if (was_empty && !c->xmit_queue_wakeup_id) { + c->xmit_queue_wakeup_id = + /* Use g_timeout_add_full so that can specify the priority */ + g_timeout_add_full(G_PRIORITY_HIGH, 0, + spice_channel_idle_wakeup, + out->channel, NULL); + } + +end: + g_mutex_unlock(&c->xmit_queue_lock); +} + +/* coroutine context */ +G_GNUC_INTERNAL +void spice_msg_out_send_internal(SpiceMsgOut *out) +{ + g_return_if_fail(out != NULL); + + spice_channel_write_msg(out->channel, out); +} + +/* + * Write all 'data' of length 'datalen' bytes out to + * the wire + */ +/* coroutine context */ +static void spice_channel_flush_wire(SpiceChannel *channel, + const void *data, + size_t datalen) +{ + SpiceChannelPrivate *c = channel->priv; + const char *ptr = data; + size_t offset = 0; + GIOCondition cond; + + while (offset < datalen) { + gssize ret; + GError *error = NULL; + + if (c->has_error) return; + + cond = 0; + if (c->tls) { + ret = SSL_write(c->ssl, ptr+offset, datalen-offset); + if (ret < 0) { + ret = SSL_get_error(c->ssl, ret); + if (ret == SSL_ERROR_WANT_READ) + cond |= G_IO_IN; + if (ret == SSL_ERROR_WANT_WRITE) + cond |= G_IO_OUT; + ret = -1; + } + } else { + ret = g_pollable_output_stream_write_nonblocking(G_POLLABLE_OUTPUT_STREAM(c->out), + ptr+offset, datalen-offset, NULL, &error); + if (ret < 0) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + cond = G_IO_OUT; + } else { + CHANNEL_DEBUG(channel, "Send error %s", error->message); + } + g_clear_error(&error); + ret = -1; + } + } + if (ret == -1) { + if (cond != 0) { + // TODO: should use g_pollable_input/output_stream_create_source() in 2.28 ? + g_coroutine_socket_wait(&c->coroutine, c->sock, cond); + continue; + } else { + CHANNEL_DEBUG(channel, "Closing the channel: spice_channel_flush %d", errno); + c->has_error = TRUE; + return; + } + } + if (ret == 0) { + CHANNEL_DEBUG(channel, "Closing the connection: spice_channel_flush"); + c->has_error = TRUE; + return; + } + offset += ret; + } +} + +#ifdef HAVE_SASL +/* + * Encode all buffered data, write all encrypted data out + * to the wire + */ +static void spice_channel_flush_sasl(SpiceChannel *channel, const void *data, size_t len) +{ + SpiceChannelPrivate *c = channel->priv; + const char *output; + unsigned int outputlen; + int err; + + err = sasl_encode(c->sasl_conn, data, len, &output, &outputlen); + if (err != SASL_OK) { + g_warning ("Failed to encode SASL data %s", + sasl_errstring(err, NULL, NULL)); + c->has_error = TRUE; + return; + } + + //CHANNEL_DEBUG(channel, "Flush SASL %d: %p %d", len, output, outputlen); + spice_channel_flush_wire(channel, output, outputlen); +} +#endif + +/* coroutine context */ +static void spice_channel_write(SpiceChannel *channel, const void *data, size_t len) +{ +#ifdef HAVE_SASL + SpiceChannelPrivate *c = channel->priv; + + if (c->sasl_conn) + spice_channel_flush_sasl(channel, data, len); + else +#endif + spice_channel_flush_wire(channel, data, len); +} + +/* coroutine context */ +static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out) +{ + uint8_t *data; + int free_data; + size_t len; + uint32_t msg_size; + + g_return_if_fail(channel != NULL); + g_return_if_fail(out != NULL); + g_return_if_fail(channel == out->channel); + + if (out->ro_check && + spice_channel_get_read_only(channel)) { + g_warning("Try to send message while read-only. Please report a bug."); + return; + } + + spice_marshaller_flush(out->marshaller); + msg_size = spice_marshaller_get_total_size(out->marshaller) - + spice_header_get_header_size(channel->priv->use_mini_header); + spice_header_set_msg_size(out->header, channel->priv->use_mini_header, msg_size); + data = spice_marshaller_linearize(out->marshaller, 0, &len, &free_data); + /* spice_msg_out_hexdump(out, data, len); */ + spice_channel_write(channel, data, len); + + if (free_data) + g_free(data); + + spice_msg_out_unref(out); +} + +#ifdef G_OS_UNIX +static ssize_t read_fd(int fd, int *msgfd) +{ + struct msghdr msg = { NULL, }; + struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; + struct cmsghdr *cmsg; + ssize_t ret; + char c; + + iov[0].iov_base = &c; + iov[0].iov_len = 1; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + + ret = recvmsg(fd, &msg, 0); + if (ret > 0) { + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + continue; + } + + memcpy(msgfd, CMSG_DATA(cmsg), sizeof(int)); + if (*msgfd < 0) { + continue; + } + } + } + return ret; +} + +G_GNUC_INTERNAL +gint spice_channel_unix_read_fd(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + gint fd = -1; + + g_return_val_if_fail(g_socket_get_family(c->sock) == G_SOCKET_FAMILY_UNIX, -1); + + while (1) { + /* g_socket_receive_message() is not convenient here because it + * reads all control messages, and overly complicated to deal with */ + if (read_fd(g_socket_get_fd(c->sock), &fd) > 0) { + break; + } + + if (errno == EWOULDBLOCK) { + g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN); + } else { + g_warning("failed to get fd: %s", g_strerror(errno)); + return -1; + } + } + + return fd; +} +#endif + +/* + * Read at least 1 more byte of data straight off the wire + * into the requested buffer. + */ +/* coroutine context */ +static int spice_channel_read_wire(SpiceChannel *channel, void *data, size_t len) +{ + SpiceChannelPrivate *c = channel->priv; + gssize ret; + GIOCondition cond; + +reread: + + if (c->has_error) return 0; /* has_error is set by disconnect(), return no error */ + + cond = 0; + if (c->tls) { + ret = SSL_read(c->ssl, data, len); + if (ret < 0) { + ret = SSL_get_error(c->ssl, ret); + if (ret == SSL_ERROR_WANT_READ) + cond |= G_IO_IN; + if (ret == SSL_ERROR_WANT_WRITE) + cond |= G_IO_OUT; + ret = -1; + } + } else { + GError *error = NULL; + ret = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(c->in), + data, len, NULL, &error); + if (ret < 0) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + cond = G_IO_IN; + } else { + CHANNEL_DEBUG(channel, "Read error %s", error->message); + } + g_clear_error(&error); + ret = -1; + } + } + + if (ret == -1) { + if (cond != 0) { + // TODO: should use g_pollable_input/output_stream_create_source() ? + g_coroutine_socket_wait(&c->coroutine, c->sock, cond); + goto reread; + } else { + c->has_error = TRUE; + return -errno; + } + } + if (ret == 0) { + CHANNEL_DEBUG(channel, "Closing the connection: spice_channel_read() - ret=0"); + c->has_error = TRUE; + return 0; + } + + return ret; +} + +#ifdef HAVE_SASL +/* + * Read at least 1 more byte of data out of the SASL decrypted + * data buffer, into the internal read buffer + */ +static int spice_channel_read_sasl(SpiceChannel *channel, void *data, size_t len) +{ + SpiceChannelPrivate *c = channel->priv; + + /* CHANNEL_DEBUG(channel, "Read %lu SASL %p size %d offset %d", len, c->sasl_decoded, */ + /* c->sasl_decoded_length, c->sasl_decoded_offset); */ + + if (c->sasl_decoded == NULL || c->sasl_decoded_length == 0) { + char encoded[8192]; /* should stay lower than maxbufsize */ + int err, ret; + + g_warn_if_fail(c->sasl_decoded_offset == 0); + + ret = spice_channel_read_wire(channel, encoded, sizeof(encoded)); + if (ret < 0) + return ret; + + err = sasl_decode(c->sasl_conn, encoded, ret, + &c->sasl_decoded, &c->sasl_decoded_length); + if (err != SASL_OK) { + g_warning("Failed to decode SASL data %s", + sasl_errstring(err, NULL, NULL)); + c->has_error = TRUE; + return -EINVAL; + } + c->sasl_decoded_offset = 0; + } + + if (c->sasl_decoded_length == 0) + return 0; + + len = MIN(c->sasl_decoded_length - c->sasl_decoded_offset, len); + memcpy(data, c->sasl_decoded + c->sasl_decoded_offset, len); + c->sasl_decoded_offset += len; + + if (c->sasl_decoded_offset == c->sasl_decoded_length) { + c->sasl_decoded_length = c->sasl_decoded_offset = 0; + c->sasl_decoded = NULL; + } + + return len; +} +#endif + +/* + * Fill the 'data' buffer up with exactly 'len' bytes worth of data + */ +/* coroutine context */ +static int spice_channel_read(SpiceChannel *channel, void *data, size_t length) +{ + SpiceChannelPrivate *c = channel->priv; + gsize len = length; + int ret; + + while (len > 0) { + if (c->has_error) return 0; /* has_error is set by disconnect(), return no error */ + +#ifdef HAVE_SASL + if (c->sasl_conn) + ret = spice_channel_read_sasl(channel, data, len); + else +#endif + ret = spice_channel_read_wire(channel, data, len); + if (ret < 0) + return ret; + g_assert(ret <= len); + len -= ret; + data = ((char*)data) + ret; +#if DEBUG + if (len > 0) + CHANNEL_DEBUG(channel, "still needs %" G_GSIZE_FORMAT, len); +#endif + } + c->total_read_bytes += length; + + return length; +} + +/* coroutine context */ +static void spice_channel_failed_authentication(SpiceChannel *channel, + gboolean invalidPassword) +{ + SpiceChannelPrivate *c = channel->priv; + + if (c->auth_needs_username && c->auth_needs_password) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME, + _("Authentication failed: password and username are required")); + else if (c->auth_needs_username) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_USERNAME, + _("Authentication failed: username is required")); + else if (c->auth_needs_password) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + _("Authentication failed: password is required")); + else if (invalidPassword) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + _("Authentication failed: password is too long")); + else + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + _("Authentication failed: password is required")); + + c->event = SPICE_CHANNEL_ERROR_AUTH; + + c->has_error = TRUE; /* force disconnect */ +} + +/* coroutine context */ +static SpiceChannelEvent spice_channel_send_spice_ticket(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + EVP_PKEY *pubkey; + int nRSASize; + BIO *bioKey; + RSA *rsa; + char *password; + uint8_t *encrypted; + int rc; + SpiceChannelEvent ret = SPICE_CHANNEL_ERROR_LINK; + + bioKey = BIO_new(BIO_s_mem()); + g_return_val_if_fail(bioKey != NULL, ret); + + BIO_write(bioKey, c->peer_msg->pub_key, SPICE_TICKET_PUBKEY_BYTES); + pubkey = d2i_PUBKEY_bio(bioKey, NULL); + g_return_val_if_fail(pubkey != NULL, ret); + + rsa = pubkey->pkey.rsa; + nRSASize = RSA_size(rsa); + + encrypted = g_alloca(nRSASize); + /* + The use of RSA encryption limit the potential maximum password length. + for RSA_PKCS1_OAEP_PADDING it is RSA_size(rsa) - 41. + */ + g_object_get(c->session, "password", &password, NULL); + if (password == NULL) + password = g_strdup(""); + if (strlen(password) > SPICE_MAX_PASSWORD_LENGTH) { + spice_channel_failed_authentication(channel, TRUE); + ret = SPICE_CHANNEL_ERROR_AUTH; + goto cleanup; + } + rc = RSA_public_encrypt(strlen(password) + 1, (uint8_t*)password, + encrypted, rsa, RSA_PKCS1_OAEP_PADDING); + g_warn_if_fail(rc > 0); + + spice_channel_write(channel, encrypted, nRSASize); + ret = SPICE_CHANNEL_NONE; + +cleanup: + memset(encrypted, 0, nRSASize); + EVP_PKEY_free(pubkey); + BIO_free(bioKey); + g_free(password); + return ret; +} + +/* coroutine context */ +static gboolean spice_channel_recv_auth(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + uint32_t link_res; + int rc; + + rc = spice_channel_read(channel, &link_res, sizeof(link_res)); + if (rc != sizeof(link_res)) { + CHANNEL_DEBUG(channel, "incomplete auth reply (%d/%" G_GSIZE_FORMAT ")", + rc, sizeof(link_res)); + c->event = SPICE_CHANNEL_ERROR_LINK; + return FALSE; + } + + if (link_res != SPICE_LINK_ERR_OK) { + CHANNEL_DEBUG(channel, "link result: reply %u", link_res); + spice_channel_failed_authentication(channel, FALSE); + return FALSE; + } + + c->state = SPICE_CHANNEL_STATE_READY; + + g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_OPENED); + + if (c->state == SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE) { + spice_channel_send_migration_handshake(channel); + } + + if (c->state != SPICE_CHANNEL_STATE_MIGRATING) + spice_channel_up(channel); + + return TRUE; +} + +G_GNUC_INTERNAL +void spice_channel_up(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + CHANNEL_DEBUG(channel, "channel up, state %u", c->state); + + if (SPICE_CHANNEL_GET_CLASS(channel)->channel_up) + SPICE_CHANNEL_GET_CLASS(channel)->channel_up(channel); +} + +/* coroutine context */ +static void spice_channel_send_link(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + uint8_t *buffer, *p; + int protocol, i; + + c->link_hdr.magic = SPICE_MAGIC; + c->link_hdr.size = sizeof(c->link_msg); + + g_object_get(c->session, "protocol", &protocol, NULL); + switch (protocol) { + case 1: /* protocol 1 == major 1, old 0.4 protocol, last active minor */ + c->link_hdr.major_version = 1; + c->link_hdr.minor_version = 3; + c->parser = spice_get_server_channel_parser1(c->channel_type, NULL); + c->marshallers = spice_message_marshallers_get1(); + break; + case SPICE_VERSION_MAJOR: /* protocol 2 == current */ + c->link_hdr.major_version = SPICE_VERSION_MAJOR; + c->link_hdr.minor_version = SPICE_VERSION_MINOR; + c->parser = spice_get_server_channel_parser(c->channel_type, NULL); + c->marshallers = spice_message_marshallers_get(); + break; + default: + g_critical("unknown major %d", protocol); + return; + } + + c->link_hdr.major_version = GUINT32_TO_LE(c->link_hdr.major_version); + c->link_hdr.minor_version = GUINT32_TO_LE(c->link_hdr.minor_version); + + c->link_msg.connection_id = GUINT32_TO_LE(spice_session_get_connection_id(c->session)); + c->link_msg.channel_type = c->channel_type; + c->link_msg.channel_id = c->channel_id; + c->link_msg.caps_offset = GUINT32_TO_LE(sizeof(c->link_msg)); + + c->link_msg.num_common_caps = GUINT32_TO_LE(c->common_caps->len); + c->link_msg.num_channel_caps = GUINT32_TO_LE(c->caps->len); + c->link_hdr.size += (c->common_caps->len + c->caps->len) * sizeof(uint32_t); + + buffer = g_malloc0(sizeof(c->link_hdr) + c->link_hdr.size); + p = buffer; + + c->link_hdr.size = GUINT32_TO_LE(c->link_hdr.size); + + memcpy(p, &c->link_hdr, sizeof(c->link_hdr)); p += sizeof(c->link_hdr); + memcpy(p, &c->link_msg, sizeof(c->link_msg)); p += sizeof(c->link_msg); + + for (i = 0; i < c->common_caps->len; i++) { + *(uint32_t *)p = GUINT32_TO_LE(g_array_index(c->common_caps, uint32_t, i)); + p += sizeof(uint32_t); + } + for (i = 0; i < c->caps->len; i++) { + *(uint32_t *)p = GUINT32_TO_LE(g_array_index(c->caps, uint32_t, i)); + p += sizeof(uint32_t); + } + CHANNEL_DEBUG(channel, "channel type %d id %d num common caps %u num caps %u", + c->channel_type, + c->channel_id, + c->common_caps->len, + c->caps->len); + spice_channel_write(channel, buffer, p - buffer); + g_free(buffer); +} + +/* coroutine context */ +static gboolean spice_channel_recv_link_hdr(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + int rc; + + rc = spice_channel_read(channel, &c->peer_hdr, sizeof(c->peer_hdr)); + if (rc != sizeof(c->peer_hdr)) { + g_warning("incomplete link header (%d/%" G_GSIZE_FORMAT ")", + rc, sizeof(c->peer_hdr)); + goto error; + } + if (c->peer_hdr.magic != SPICE_MAGIC) { + g_warning("invalid SPICE_MAGIC!"); + goto error; + } + + CHANNEL_DEBUG(channel, "Peer version: %u:%u", + GUINT32_FROM_LE(c->peer_hdr.major_version), + GUINT32_FROM_LE(c->peer_hdr.minor_version)); + if (c->peer_hdr.major_version != c->link_hdr.major_version) { + g_warning("major mismatch (got %u, expected %u)", + c->peer_hdr.major_version, c->link_hdr.major_version); + goto error; + } + + c->peer_hdr.major_version = GUINT32_FROM_LE(c->peer_hdr.major_version); + c->peer_hdr.minor_version = GUINT32_FROM_LE(c->peer_hdr.minor_version); + c->peer_hdr.size = GUINT32_FROM_LE(c->peer_hdr.size); + + c->peer_msg = g_malloc0(c->peer_hdr.size); + if (c->peer_msg == NULL) { + g_warning("invalid peer header size: %u", c->peer_hdr.size); + goto error; + } + + return TRUE; + +error: + /* Windows socket seems to give early CONNRESET errors. The server + does not linger when closing the socket if the protocol is + incompatible. Try with the oldest protocol in this case: */ + if (c->link_hdr.major_version != 1) { + SPICE_DEBUG("%s: error, switching to protocol 1 (spice 0.4)", c->name); + c->state = SPICE_CHANNEL_STATE_RECONNECTING; + g_object_set(c->session, "protocol", 1, NULL); + return FALSE; + } + + c->event = SPICE_CHANNEL_ERROR_LINK; + return FALSE; +} + +#ifdef HAVE_SASL +/* + * NB, keep in sync with similar method in spice/server/reds.c + */ +static gchar *addr_to_string(GSocketAddress *addr) +{ + GInetSocketAddress *iaddr = G_INET_SOCKET_ADDRESS(addr); + guint16 port; + GInetAddress *host; + gchar *hoststr; + gchar *ret; + + host = g_inet_socket_address_get_address(iaddr); + port = g_inet_socket_address_get_port(iaddr); + hoststr = g_inet_address_to_string(host); + + ret = g_strdup_printf("%s;%hu", hoststr, port); + g_free(hoststr); + + return ret; +} + +static gboolean +spice_channel_gather_sasl_credentials(SpiceChannel *channel, + sasl_interact_t *interact) +{ + SpiceChannelPrivate *c; + int ninteract; + gboolean ret = TRUE; + + g_return_val_if_fail(channel != NULL, FALSE); + g_return_val_if_fail(channel->priv != NULL, FALSE); + + c = channel->priv; + + /* FIXME: we could keep connection open and ask connection details if missing */ + + for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) { + switch (interact[ninteract].id) { + case SASL_CB_AUTHNAME: + case SASL_CB_USER: + c->auth_needs_username = TRUE; + break; + case SASL_CB_PASS: + c->auth_needs_password = TRUE; + break; + } + } + + for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) { + switch (interact[ninteract].id) { + case SASL_CB_AUTHNAME: + case SASL_CB_USER: + if (spice_session_get_username(c->session) != NULL) { + interact[ninteract].result = spice_session_get_username(c->session); + interact[ninteract].len = strlen(interact[ninteract].result); + } + break; + + case SASL_CB_PASS: + if (spice_session_get_password(c->session) == NULL) { + /* Even if we reach this point, we have to continue looking for + * SASL_CB_AUTHNAME|SASL_CB_USER, otherwise we would return a + * wrong error to the applications */ + ret = FALSE; + continue; + } + + interact[ninteract].result = spice_session_get_password(c->session); + interact[ninteract].len = strlen(interact[ninteract].result); + break; + } + } + + CHANNEL_DEBUG(channel, "Filled SASL interact"); + + return ret; +} + +/* + * + * Init msg from server + * + * u32 mechlist-length + * u8-array mechlist-string + * + * Start msg to server + * + * u32 mechname-length + * u8-array mechname-string + * u32 clientout-length + * u8-array clientout-string + * + * Start msg from server + * + * u32 serverin-length + * u8-array serverin-string + * u8 continue + * + * Step msg to server + * + * u32 clientout-length + * u8-array clientout-string + * + * Step msg from server + * + * u32 serverin-length + * u8-array serverin-string + * u8 continue + */ + +#define SASL_MAX_MECHLIST_LEN 300 +#define SASL_MAX_MECHNAME_LEN 100 +#define SASL_MAX_DATA_LEN (1024 * 1024) + +/* Perform the SASL authentication process + */ +static gboolean spice_channel_perform_auth_sasl(SpiceChannel *channel) +{ + SpiceChannelPrivate *c; + sasl_conn_t *saslconn = NULL; + sasl_security_properties_t secprops; + const char *clientout; + char *serverin = NULL; + unsigned int clientoutlen; + int err; + char *localAddr = NULL, *remoteAddr = NULL; + const void *val; + sasl_ssf_t ssf; + static const sasl_callback_t saslcb[] = { + { .id = SASL_CB_USER }, + { .id = SASL_CB_AUTHNAME }, + { .id = SASL_CB_PASS }, + { .id = 0 }, + }; + sasl_interact_t *interact = NULL; + guint32 len; + char *mechlist = NULL; + const char *mechname; + gboolean ret = FALSE; + GSocketAddress *addr = NULL; + guint8 complete; + + g_return_val_if_fail(channel != NULL, FALSE); + g_return_val_if_fail(channel->priv != NULL, FALSE); + + c = channel->priv; + + /* Sets up the SASL library as a whole */ + err = sasl_client_init(NULL); + CHANNEL_DEBUG(channel, "Client initialize SASL authentication %d", err); + if (err != SASL_OK) { + g_critical("failed to initialize SASL library: %d (%s)", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + /* Get local address in form IPADDR:PORT */ + addr = g_socket_get_local_address(c->sock, NULL); + if (!addr) { + g_critical("failed to get local address"); + goto error; + } + if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 || + g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) && + (localAddr = addr_to_string(addr)) == NULL) + goto error; + g_clear_object(&addr); + + /* Get remote address in form IPADDR:PORT */ + addr = g_socket_get_remote_address(c->sock, NULL); + if (!addr) { + g_critical("failed to get peer address"); + goto error; + } + if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 || + g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) && + (remoteAddr = addr_to_string(addr)) == NULL) + goto error; + g_clear_object(&addr); + + CHANNEL_DEBUG(channel, "Client SASL new host:'%s' local:'%s' remote:'%s'", + spice_session_get_host(c->session), localAddr, remoteAddr); + + /* Setup a handle for being a client */ + err = sasl_client_new("spice", + spice_session_get_host(c->session), + localAddr, + remoteAddr, + saslcb, + SASL_SUCCESS_DATA, + &saslconn); + + if (err != SASL_OK) { + g_critical("Failed to create SASL client context: %d (%s)", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + if (c->ssl) { + sasl_ssf_t ssf; + + ssf = SSL_get_cipher_bits(c->ssl, NULL); + err = sasl_setprop(saslconn, SASL_SSF_EXTERNAL, &ssf); + if (err != SASL_OK) { + g_critical("cannot set SASL external SSF %d (%s)", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + } + + memset(&secprops, 0, sizeof secprops); + /* If we've got TLS, we don't care about SSF */ + secprops.min_ssf = c->ssl ? 0 : 56; /* Equiv to DES supported by all Kerberos */ + secprops.max_ssf = c->ssl ? 0 : 100000; /* Very strong ! AES == 256 */ + secprops.maxbufsize = 100000; + /* If we're not TLS, then forbid any anonymous or trivially crackable auth */ + secprops.security_flags = c->ssl ? 0 : + SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; + + err = sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops); + if (err != SASL_OK) { + g_critical("cannot set security props %d (%s)", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + + /* Get the supported mechanisms from the server */ + spice_channel_read(channel, &len, sizeof(len)); + if (c->has_error) + goto error; + if (len > SASL_MAX_MECHLIST_LEN) { + g_critical("mechlistlen %u too long", len); + goto error; + } + + mechlist = g_malloc0(len + 1); + spice_channel_read(channel, mechlist, len); + mechlist[len] = '\0'; + if (c->has_error) { + goto error; + } + +restart: + /* Start the auth negotiation on the client end first */ + CHANNEL_DEBUG(channel, "Client start negotiation mechlist '%s'", mechlist); + err = sasl_client_start(saslconn, + mechlist, + &interact, + &clientout, + &clientoutlen, + &mechname); + if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { + g_critical("Failed to start SASL negotiation: %d (%s)", + err, sasl_errdetail(saslconn)); + goto error; + } + + /* Need to gather some credentials from the client */ + if (err == SASL_INTERACT) { + if (!spice_channel_gather_sasl_credentials(channel, interact)) { + CHANNEL_DEBUG(channel, "Failed to collect auth credentials"); + goto error; + } + goto restart; + } + + CHANNEL_DEBUG(channel, "Server start negotiation with mech %s. Data %u bytes %p '%s'", + mechname, clientoutlen, clientout, clientout); + + if (clientoutlen > SASL_MAX_DATA_LEN) { + g_critical("SASL negotiation data too long: %u bytes", + clientoutlen); + goto error; + } + + /* Send back the chosen mechname */ + len = strlen(mechname); + spice_channel_write(channel, &len, sizeof(guint32)); + spice_channel_write(channel, mechname, len); + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (clientout) { + len = clientoutlen + 1; + spice_channel_write(channel, &len, sizeof(guint32)); + spice_channel_write(channel, clientout, len); + } else { + len = 0; + spice_channel_write(channel, &len, sizeof(guint32)); + } + + if (c->has_error) + goto error; + + CHANNEL_DEBUG(channel, "Getting sever start negotiation reply"); + /* Read the 'START' message reply from server */ + spice_channel_read(channel, &len, sizeof(len)); + if (c->has_error) + goto error; + if (len > SASL_MAX_DATA_LEN) { + g_critical("SASL negotiation data too long: %u bytes", + len); + goto error; + } + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (len > 0) { + serverin = g_malloc0(len); + spice_channel_read(channel, serverin, len); + serverin[len - 1] = '\0'; + len--; + } else { + serverin = NULL; + } + spice_channel_read(channel, &complete, sizeof(guint8)); + if (c->has_error) + goto error; + + CHANNEL_DEBUG(channel, "Client start result complete: %d. Data %u bytes %p '%s'", + complete, len, serverin, serverin); + + /* Loop-the-loop... + * Even if the server has completed, the client must *always* do at least one step + * in this loop to verify the server isn't lying about something. Mutual auth */ + for (;;) { + if (complete && err == SASL_OK) + break; + + restep: + err = sasl_client_step(saslconn, + serverin, + len, + &interact, + &clientout, + &clientoutlen); + if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { + g_critical("Failed SASL step: %d (%s)", + err, sasl_errdetail(saslconn)); + goto error; + } + + /* Need to gather some credentials from the client */ + if (err == SASL_INTERACT) { + if (!spice_channel_gather_sasl_credentials(channel, + interact)) { + CHANNEL_DEBUG(channel, "%s", "Failed to collect auth credentials"); + goto error; + } + goto restep; + } + + g_clear_pointer(&serverin, g_free); + + CHANNEL_DEBUG(channel, "Client step result %d. Data %u bytes %p '%s'", err, clientoutlen, clientout, clientout); + + /* Previous server call showed completion & we're now locally complete too */ + if (complete && err == SASL_OK) + break; + + /* Not done, prepare to talk with the server for another iteration */ + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (clientout) { + len = clientoutlen + 1; + spice_channel_write(channel, &len, sizeof(guint32)); + spice_channel_write(channel, clientout, len); + } else { + len = 0; + spice_channel_write(channel, &len, sizeof(guint32)); + } + + if (c->has_error) + goto error; + + CHANNEL_DEBUG(channel, "Server step with %u bytes %p", clientoutlen, clientout); + + spice_channel_read(channel, &len, sizeof(guint32)); + if (c->has_error) + goto error; + if (len > SASL_MAX_DATA_LEN) { + g_critical("SASL negotiation data too long: %u bytes", len); + goto error; + } + + /* NB, distinction of NULL vs "" is *critical* in SASL */ + if (len) { + serverin = g_malloc0(len); + spice_channel_read(channel, serverin, len); + serverin[len - 1] = '\0'; + len--; + } else { + serverin = NULL; + } + + spice_channel_read(channel, &complete, sizeof(guint8)); + if (c->has_error) + goto error; + + CHANNEL_DEBUG(channel, "Client step result complete: %d. Data %u bytes %p '%s'", + complete, len, serverin, serverin); + + /* This server call shows complete, and earlier client step was OK */ + if (complete) { + g_clear_pointer(&serverin, g_free); + if (err == SASL_CONTINUE) /* something went wrong */ + goto complete; + break; + } + } + + /* Check for suitable SSF if non-TLS */ + if (!c->ssl) { + err = sasl_getprop(saslconn, SASL_SSF, &val); + if (err != SASL_OK) { + g_critical("cannot query SASL ssf on connection %d (%s)", + err, sasl_errstring(err, NULL, NULL)); + goto error; + } + ssf = *(const int *)val; + CHANNEL_DEBUG(channel, "SASL SSF value %u", ssf); + if (ssf < 56) { /* 56 == DES level, good for Kerberos */ + g_critical("negotiation SSF %u was not strong enough", ssf); + goto error; + } + } + +complete: + CHANNEL_DEBUG(channel, "%s", "SASL authentication complete"); + spice_channel_read(channel, &len, sizeof(len)); + if (len == SPICE_LINK_ERR_OK) { + ret = TRUE; + /* This must come *after* check-auth-result, because the former + * is defined to be sent unencrypted, and setting saslconn turns + * on the SSF layer encryption processing */ + c->sasl_conn = saslconn; + goto cleanup; + } + +error: + if (saslconn) + sasl_dispose(&saslconn); + + spice_channel_failed_authentication(channel, FALSE); + ret = FALSE; + +cleanup: + g_free(localAddr); + g_free(remoteAddr); + g_free(mechlist); + g_free(serverin); + g_clear_object(&addr); + return ret; +} +#endif /* HAVE_SASL */ + +/* coroutine context */ +static gboolean spice_channel_recv_link_msg(SpiceChannel *channel) +{ + SpiceChannelPrivate *c; + int rc, num_caps, i; + uint32_t *caps, num_channel_caps, num_common_caps; + SpiceChannelEvent event = SPICE_CHANNEL_ERROR_LINK; + + g_return_val_if_fail(channel != NULL, FALSE); + g_return_val_if_fail(channel->priv != NULL, FALSE); + + c = channel->priv; + + rc = spice_channel_read(channel, (uint8_t*)c->peer_msg + c->peer_pos, + c->peer_hdr.size - c->peer_pos); + c->peer_pos += rc; + if (c->peer_pos != c->peer_hdr.size) { + g_critical("%s: %s: incomplete link reply (%d/%u)", + c->name, __FUNCTION__, rc, c->peer_hdr.size); + goto error; + } + switch (c->peer_msg->error) { + case SPICE_LINK_ERR_OK: + /* nothing */ + break; + case SPICE_LINK_ERR_NEED_SECURED: + c->state = SPICE_CHANNEL_STATE_RECONNECTING; + CHANNEL_DEBUG(channel, "switching to tls"); + c->tls = TRUE; + return FALSE; + default: + g_warning("%s: %s: unhandled error %u", + c->name, __FUNCTION__, c->peer_msg->error); + goto error; + } + + num_channel_caps = GUINT32_FROM_LE(c->peer_msg->num_channel_caps); + num_common_caps = GUINT32_FROM_LE(c->peer_msg->num_common_caps); + + num_caps = num_channel_caps + num_common_caps; + CHANNEL_DEBUG(channel, "%s: %d caps", __FUNCTION__, num_caps); + + /* see original spice/client code: */ + /* g_return_if_fail(c->peer_msg + c->peer_msg->caps_offset * sizeof(uint32_t) > c->peer_msg + c->peer_hdr.size); */ + + caps = (uint32_t *)((uint8_t *)c->peer_msg + GUINT32_FROM_LE(c->peer_msg->caps_offset)); + + g_array_set_size(c->remote_common_caps, num_common_caps); + for (i = 0; i < num_common_caps; i++, caps++) { + g_array_index(c->remote_common_caps, uint32_t, i) = GUINT32_FROM_LE(*caps); + CHANNEL_DEBUG(channel, "got common caps %d:0x%X", i, GUINT32_FROM_LE(*caps)); + } + + g_array_set_size(c->remote_caps, num_channel_caps); + for (i = 0; i < num_channel_caps; i++, caps++) { + g_array_index(c->remote_caps, uint32_t, i) = GUINT32_FROM_LE(*caps); + CHANNEL_DEBUG(channel, "got channel caps %d:0x%X", i, GUINT32_FROM_LE(*caps)); + } + + if (!spice_channel_test_common_capability(channel, + SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION)) { + CHANNEL_DEBUG(channel, "Server supports spice ticket auth only"); + if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) + goto error; + } else { + SpiceLinkAuthMechanism auth = { 0, }; + +#ifdef HAVE_SASL + if (spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_AUTH_SASL)) { + CHANNEL_DEBUG(channel, "Choosing SASL mechanism"); + auth.auth_mechanism = SPICE_COMMON_CAP_AUTH_SASL; + spice_channel_write(channel, &auth, sizeof(auth)); + if (!spice_channel_perform_auth_sasl(channel)) + return FALSE; + } else +#endif + if (spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_AUTH_SPICE)) { + auth.auth_mechanism = SPICE_COMMON_CAP_AUTH_SPICE; + spice_channel_write(channel, &auth, sizeof(auth)); + if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) + goto error; + } else { + g_warning("No compatible AUTH mechanism"); + goto error; + } + } + c->use_mini_header = spice_channel_test_common_capability(channel, + SPICE_COMMON_CAP_MINI_HEADER); + CHANNEL_DEBUG(channel, "use mini header: %d", c->use_mini_header); + return TRUE; + +error: + c->has_error = TRUE; + c->event = event; + return FALSE; +} + +/* system context */ +G_GNUC_INTERNAL +void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel) +{ + GCoroutine *c; + + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + c = &channel->priv->coroutine; + + if (cancel) + g_coroutine_condition_cancel(c); + + g_coroutine_wakeup(c); +} + +G_GNUC_INTERNAL +gboolean spice_channel_get_read_only(SpiceChannel *channel) +{ + return spice_session_get_read_only(channel->priv->session); +} + +/* coroutine context */ +G_GNUC_INTERNAL +void spice_channel_recv_msg(SpiceChannel *channel, + handler_msg_in msg_handler, gpointer data) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgIn *in; + int msg_size; + int msg_type; + int sub_list_offset = 0; + + in = spice_msg_in_new(channel); + + /* receive message */ + spice_channel_read(channel, in->header, + spice_header_get_header_size(c->use_mini_header)); + if (c->has_error) + goto end; + + msg_size = spice_header_get_msg_size(in->header, c->use_mini_header); + /* FIXME: do not allow others to take ref on in, and use realloc here? + * this would avoid malloc/free on each message? + */ + in->data = g_malloc0(msg_size); + spice_channel_read(channel, in->data, msg_size); + if (c->has_error) + goto end; + in->dpos = msg_size; + + msg_type = spice_header_get_msg_type(in->header, c->use_mini_header); + sub_list_offset = spice_header_get_msg_sub_list(in->header, c->use_mini_header); + + if (msg_type == SPICE_MSG_LIST || sub_list_offset) { + SpiceSubMessageList *sub_list; + SpiceSubMessage *sub; + SpiceMsgIn *sub_in; + int i; + + sub_list = (SpiceSubMessageList *)(in->data + sub_list_offset); + for (i = 0; i < sub_list->size; i++) { + sub = (SpiceSubMessage *)(in->data + sub_list->sub_messages[i]); + sub_in = spice_msg_in_sub_new(channel, in, sub); + sub_in->parsed = c->parser(sub_in->data, sub_in->data + sub_in->dpos, + spice_header_get_msg_type(sub_in->header, + c->use_mini_header), + c->peer_hdr.minor_version, + &sub_in->psize, &sub_in->pfree); + if (sub_in->parsed == NULL) { + g_critical("failed to parse sub-message: %s type %d", + c->name, spice_header_get_msg_type(sub_in->header, c->use_mini_header)); + goto end; + } + msg_handler(channel, sub_in, data); + spice_msg_in_unref(sub_in); + } + } + + /* ack message */ + if (c->message_ack_count) { + c->message_ack_count--; + if (!c->message_ack_count) { + SpiceMsgOut *out = spice_msg_out_new(channel, SPICE_MSGC_ACK); + spice_msg_out_send_internal(out); + c->message_ack_count = c->message_ack_window; + } + } + + if (msg_type == SPICE_MSG_LIST) { + goto end; + } + + /* parse message */ + in->parsed = c->parser(in->data, in->data + msg_size, msg_type, + c->peer_hdr.minor_version, &in->psize, &in->pfree); + if (in->parsed == NULL) { + g_critical("failed to parse message: %s type %d", + c->name, msg_type); + goto end; + } + + /* process message */ + /* spice_msg_in_hexdump(in); */ + msg_handler(channel, in, data); + +end: + /* If the server uses full header, the serial is not necessarily equal + * to c->in_serial (the server can sometimes skip serials) */ + c->last_message_serial = spice_header_get_in_msg_serial(in); + c->in_serial++; + spice_msg_in_unref(in); +} + +static const char *to_string[] = { + NULL, + [ SPICE_CHANNEL_MAIN ] = "main", + [ SPICE_CHANNEL_DISPLAY ] = "display", + [ SPICE_CHANNEL_INPUTS ] = "inputs", + [ SPICE_CHANNEL_CURSOR ] = "cursor", + [ SPICE_CHANNEL_PLAYBACK ] = "playback", + [ SPICE_CHANNEL_RECORD ] = "record", + [ SPICE_CHANNEL_TUNNEL ] = "tunnel", + [ SPICE_CHANNEL_SMARTCARD ] = "smartcard", + [ SPICE_CHANNEL_USBREDIR ] = "usbredir", + [ SPICE_CHANNEL_PORT ] = "port", + [ SPICE_CHANNEL_WEBDAV ] = "webdav", +}; + +/** + * spice_channel_type_to_string: + * @type: a channel-type property value + * + * Convert a channel-type property value to a string. + * + * Returns: string representation of @type. + * Since: 0.20 + **/ +const gchar* spice_channel_type_to_string(gint type) +{ + const char *str = NULL; + + if (type >= 0 && type < G_N_ELEMENTS(to_string)) { + str = to_string[type]; + } + + return str ? str : "unknown channel type"; +} + +/** + * spice_channel_string_to_type: + * @str: a string representation of the channel-type property + * + * Convert a channel-type property value to a string. + * + * Returns: the channel-type property value for a @str channel + * Since: 0.21 + **/ +gint spice_channel_string_to_type(const gchar *str) +{ + int i; + + g_return_val_if_fail(str != NULL, -1); + + for (i = 0; i < G_N_ELEMENTS(to_string); i++) + if (g_strcmp0(str, to_string[i]) == 0) + return i; + + return -1; +} + +G_GNUC_INTERNAL +gchar *spice_channel_supported_string(void) +{ + return g_strjoin(", ", + spice_channel_type_to_string(SPICE_CHANNEL_MAIN), + spice_channel_type_to_string(SPICE_CHANNEL_DISPLAY), + spice_channel_type_to_string(SPICE_CHANNEL_INPUTS), + spice_channel_type_to_string(SPICE_CHANNEL_CURSOR), + spice_channel_type_to_string(SPICE_CHANNEL_PLAYBACK), + spice_channel_type_to_string(SPICE_CHANNEL_RECORD), +#ifdef USE_SMARTCARD + spice_channel_type_to_string(SPICE_CHANNEL_SMARTCARD), +#endif +#ifdef USE_USBREDIR + spice_channel_type_to_string(SPICE_CHANNEL_USBREDIR), +#endif +#ifdef USE_PHODAV + spice_channel_type_to_string(SPICE_CHANNEL_WEBDAV), +#endif + NULL); +} + + +/** + * spice_channel_new: + * @s: the @SpiceSession the channel is linked to + * @type: the requested SPICECHANNELPRIVATE type + * @id: the channel-id + * + * Create a new #SpiceChannel of type @type, and channel ID @id. + * + * Returns: a weak reference to #SpiceChannel, the session owns the reference + **/ +SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id) +{ + SpiceChannel *channel; + GType gtype = 0; + + g_return_val_if_fail(s != NULL, NULL); + + switch (type) { + case SPICE_CHANNEL_MAIN: + gtype = SPICE_TYPE_MAIN_CHANNEL; + break; + case SPICE_CHANNEL_DISPLAY: + gtype = SPICE_TYPE_DISPLAY_CHANNEL; + break; + case SPICE_CHANNEL_CURSOR: + gtype = SPICE_TYPE_CURSOR_CHANNEL; + break; + case SPICE_CHANNEL_INPUTS: + gtype = SPICE_TYPE_INPUTS_CHANNEL; + break; + case SPICE_CHANNEL_PLAYBACK: + case SPICE_CHANNEL_RECORD: { + if (!spice_session_get_audio_enabled(s)) { + SPICE_DEBUG("audio channel is disabled, not creating it"); + return NULL; + } + gtype = type == SPICE_CHANNEL_RECORD ? + SPICE_TYPE_RECORD_CHANNEL : SPICE_TYPE_PLAYBACK_CHANNEL; + break; + } +#ifdef USE_SMARTCARD + case SPICE_CHANNEL_SMARTCARD: { + if (!spice_session_get_smartcard_enabled(s)) { + SPICE_DEBUG("smartcard channel is disabled, not creating it"); + return NULL; + } + gtype = SPICE_TYPE_SMARTCARD_CHANNEL; + break; + } +#endif +#ifdef USE_USBREDIR + case SPICE_CHANNEL_USBREDIR: { + if (!spice_session_get_usbredir_enabled(s)) { + SPICE_DEBUG("usbredir channel is disabled, not creating it"); + return NULL; + } + gtype = SPICE_TYPE_USBREDIR_CHANNEL; + break; + } +#endif +#ifdef USE_PHODAV + case SPICE_CHANNEL_WEBDAV: { + gtype = SPICE_TYPE_WEBDAV_CHANNEL; + break; + } +#endif + case SPICE_CHANNEL_PORT: + gtype = SPICE_TYPE_PORT_CHANNEL; + break; + default: + SPICE_DEBUG("unsupported channel kind: %s: %d", + spice_channel_type_to_string(type), type); + return NULL; + } + channel = SPICE_CHANNEL(g_object_new(gtype, + "spice-session", s, + "channel-type", type, + "channel-id", id, + NULL)); + return channel; +} + +/** + * spice_channel_destroy: + * @channel: a #SpiceChannel + * + * Disconnect and unref the @channel. + * + * Deprecated: 0.27: this function has been deprecated because it is + * misleading, the object is not actually destroyed. Instead, it is + * recommended to call explicitely spice_channel_disconnect() and + * g_object_unref(). + **/ +void spice_channel_destroy(SpiceChannel *channel) +{ + g_return_if_fail(channel != NULL); + + CHANNEL_DEBUG(channel, "channel destroy"); + spice_channel_disconnect(channel, SPICE_CHANNEL_NONE); + g_object_unref(channel); +} + +/* any context */ +static void spice_channel_flushed(SpiceChannel *channel, gboolean success) +{ + SpiceChannelPrivate *c = channel->priv; + GSList *l; + + for (l = c->flushing; l != NULL; l = l->next) { + g_task_return_boolean(G_TASK(l->data), success); + } + + g_slist_free_full(c->flushing, g_object_unref); + c->flushing = NULL; +} + +/* coroutine context */ +static void spice_channel_iterate_write(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + + do { + g_mutex_lock(&c->xmit_queue_lock); + out = g_queue_pop_head(&c->xmit_queue); + g_mutex_unlock(&c->xmit_queue_lock); + if (out) { + guint32 size = spice_marshaller_get_total_size(out->marshaller); + c->xmit_queue_size = (c->xmit_queue_size < size) ? 0 : c->xmit_queue_size - size; + spice_channel_write_msg(channel, out); + } + } while (out); + + spice_channel_flushed(channel, TRUE); +} + +/* coroutine context */ +static void spice_channel_iterate_read(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN); + + /* treat all incoming data (block on message completion) */ + while (!c->has_error && + c->state != SPICE_CHANNEL_STATE_MIGRATING && + g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(c->in)) + ) { do + spice_channel_recv_msg(channel, + (handler_msg_in)SPICE_CHANNEL_GET_CLASS(channel)->handle_msg, NULL); +#ifdef HAVE_SASL + /* flush the sasl buffer too */ + while (c->sasl_decoded != NULL); +#else + while (FALSE); +#endif + } + +} + +static gboolean wait_migration(gpointer data) +{ + SpiceChannel *channel = SPICE_CHANNEL(data); + SpiceChannelPrivate *c = channel->priv; + + if (c->state != SPICE_CHANNEL_STATE_MIGRATING) { + CHANNEL_DEBUG(channel, "unfreeze channel"); + return TRUE; + } + + return FALSE; +} + +/* coroutine context */ +static gboolean spice_channel_iterate(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + if (c->state == SPICE_CHANNEL_STATE_MIGRATING && + !g_coroutine_condition_wait(&c->coroutine, wait_migration, channel)) + CHANNEL_DEBUG(channel, "migration wait cancelled"); + + /* flush any pending write and read */ + if (!c->has_error) + SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); + if (!c->has_error) + SPICE_CHANNEL_GET_CLASS(channel)->iterate_read(channel); + + if (c->has_error) { + GIOCondition ret; + + if (!c->sock) + return FALSE; + + /* We don't want to report an error if the socket was closed gracefully + * on the other end (VM shutdown) */ + ret = g_socket_condition_check(c->sock, G_IO_IN | G_IO_ERR); + + if (ret & G_IO_ERR) { + CHANNEL_DEBUG(channel, "channel got error"); + + if (c->state > SPICE_CHANNEL_STATE_CONNECTING) { + if (c->state == SPICE_CHANNEL_STATE_READY) + c->event = SPICE_CHANNEL_ERROR_IO; + else + c->event = SPICE_CHANNEL_ERROR_LINK; + } + } + return FALSE; + } + + return TRUE; +} + +/* we use an idle function to allow the coroutine to exit before we actually + * unref the object since the coroutine's state is part of the object */ +static gboolean spice_channel_delayed_unref(gpointer data) +{ + SpiceChannel *channel = SPICE_CHANNEL(data); + SpiceChannelPrivate *c = channel->priv; + gboolean was_ready = c->state == SPICE_CHANNEL_STATE_READY; + SpiceSession *session; + + CHANNEL_DEBUG(channel, "Delayed unref channel %p", channel); + + g_return_val_if_fail(c->coroutine.coroutine.exited == TRUE, FALSE); + + c->state = SPICE_CHANNEL_STATE_UNCONNECTED; + + session = spice_channel_get_session(channel); + if (session && spice_session_is_for_migration(session)) { + /* error during migration - abort migration */ + spice_session_abort_migration(session); + return FALSE; + } + + if (c->event != SPICE_CHANNEL_NONE) { + g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, c->event); + c->event = SPICE_CHANNEL_NONE; + g_clear_error(&c->error); + } + + if (was_ready) + g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_CLOSED); + + g_object_unref(G_OBJECT(data)); + + return FALSE; +} + +static X509_LOOKUP_METHOD spice_x509_mem_lookup = { + "spice_x509_mem_lookup", + 0 +}; + +static int spice_channel_load_ca(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + X509_LOOKUP *lookup; + BIO *in; + int i, count = 0; + guint8 *ca; + guint size; + const gchar *ca_file; + int rc; + + g_return_val_if_fail(c->ctx != NULL, 0); + + lookup = X509_STORE_add_lookup(c->ctx->cert_store, &spice_x509_mem_lookup); + ca_file = spice_session_get_ca_file(c->session); + spice_session_get_ca(c->session, &ca, &size); + + CHANNEL_DEBUG(channel, "Load CA, file: %s, data: %p", ca_file, ca); + + if (ca != NULL) { + in = BIO_new_mem_buf(ca, size); + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + BIO_free(in); + + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + X509_STORE_add_cert(lookup->store_ctx, itmp->x509); + count++; + } + if (itmp->crl) { + X509_STORE_add_crl(lookup->store_ctx, itmp->crl); + count++; + } + } + + sk_X509_INFO_pop_free(inf, X509_INFO_free); + } + + if (ca_file != NULL) { + rc = SSL_CTX_load_verify_locations(c->ctx, ca_file, NULL); + if (rc != 1) + g_warning("loading ca certs from %s failed", ca_file); + else + count++; + } + + if (count == 0) { + rc = SSL_CTX_set_default_verify_paths(c->ctx); + if (rc != 1) + g_warning("loading ca certs from default location failed"); + else + count++; + } + + return count; +} + +/** + * spice_channel_get_error: + * @channel: a #SpiceChannel + * + * Retrieves the #GError currently set on channel, if the #SpiceChannel + * is in error state and can provide additional error details. + * + * Returns: the pointer to the error, or %NULL + * Since: 0.24 + **/ +const GError* spice_channel_get_error(SpiceChannel *self) +{ + SpiceChannelPrivate *c; + + g_return_val_if_fail(SPICE_IS_CHANNEL(self), NULL); + c = self->priv; + + return c->error; +} + +/* coroutine context */ +static void *spice_channel_coroutine(void *data) +{ + SpiceChannel *channel = SPICE_CHANNEL(data); + SpiceChannelPrivate *c = channel->priv; + guint verify; + int rc, delay_val = 1; + /* When some other SSL/TLS version becomes obsolete, add it to this + * variable. */ + long ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + + CHANNEL_DEBUG(channel, "Started background coroutine %p", &c->coroutine); + + if (spice_session_get_client_provided_socket(c->session)) { + if (c->fd < 0) { + g_critical("fd not provided!"); + c->event = SPICE_CHANNEL_ERROR_CONNECT; + goto cleanup; + } + + if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) { + CHANNEL_DEBUG(channel, "Failed to open socket from fd %d", c->fd); + c->event = SPICE_CHANNEL_ERROR_CONNECT; + goto cleanup; + } + + g_socket_set_blocking(c->sock, FALSE); + g_socket_set_keepalive(c->sock, TRUE); + c->conn = g_socket_connection_factory_create_connection(c->sock); + goto connected; + } + + +reconnect: + c->conn = spice_session_channel_open_host(c->session, channel, &c->tls, &c->error); + if (c->conn == NULL) { + if (!c->error && !c->tls) { + CHANNEL_DEBUG(channel, "trying with TLS port"); + c->tls = true; /* FIXME: does that really work with provided fd */ + goto reconnect; + } else { + CHANNEL_DEBUG(channel, "Connect error"); + c->event = SPICE_CHANNEL_ERROR_CONNECT; + goto cleanup; + } + } + c->sock = g_object_ref(g_socket_connection_get_socket(c->conn)); + + if (c->tls) { + c->ctx = SSL_CTX_new(SSLv23_method()); + if (c->ctx == NULL) { + g_critical("SSL_CTX_new failed"); + c->event = SPICE_CHANNEL_ERROR_TLS; + goto cleanup; + } + + SSL_CTX_set_options(c->ctx, ssl_options); + + verify = spice_session_get_verify(c->session); + if (verify & + (SPICE_SESSION_VERIFY_SUBJECT | SPICE_SESSION_VERIFY_HOSTNAME)) { + rc = spice_channel_load_ca(channel); + if (rc == 0) { + g_warning("no cert loaded"); + if (verify & SPICE_SESSION_VERIFY_PUBKEY) { + g_warning("only pubkey active"); + verify = SPICE_SESSION_VERIFY_PUBKEY; + } else { + c->event = SPICE_CHANNEL_ERROR_TLS; + goto cleanup; + } + } + } + + { + const gchar *ciphers = spice_session_get_ciphers(c->session); + if (ciphers != NULL) { + rc = SSL_CTX_set_cipher_list(c->ctx, ciphers); + if (rc != 1) + g_warning("loading cipher list %s failed", ciphers); + } + } + + c->ssl = SSL_new(c->ctx); + if (c->ssl == NULL) { + g_critical("SSL_new failed"); + c->event = SPICE_CHANNEL_ERROR_TLS; + goto cleanup; + } + + + BIO *bio = bio_new_giostream(G_IO_STREAM(c->conn)); + SSL_set_bio(c->ssl, bio, bio); + + { + guint8 *pubkey; + guint pubkey_len; + + spice_session_get_pubkey(c->session, &pubkey, &pubkey_len); + c->sslverify = spice_openssl_verify_new(c->ssl, verify, + spice_session_get_host(c->session), + (char*)pubkey, pubkey_len, + spice_session_get_cert_subject(c->session)); + } + +ssl_reconnect: + rc = SSL_connect(c->ssl); + if (rc <= 0) { + rc = SSL_get_error(c->ssl, rc); + if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) { + g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP); + goto ssl_reconnect; + } else { + g_warning("%s: SSL_connect: %s", + c->name, ERR_error_string(rc, NULL)); + c->event = SPICE_CHANNEL_ERROR_TLS; + goto cleanup; + } + } + } + +connected: + c->has_error = FALSE; + c->in = g_io_stream_get_input_stream(G_IO_STREAM(c->conn)); + c->out = g_io_stream_get_output_stream(G_IO_STREAM(c->conn)); + + rc = setsockopt(g_socket_get_fd(c->sock), IPPROTO_TCP, TCP_NODELAY, + (const char*)&delay_val, sizeof(delay_val)); + if ((rc != 0) +#ifdef ENOTSUP + && (errno != ENOTSUP) +#endif + ) { + g_warning("%s: could not set sockopt TCP_NODELAY: %s", c->name, + strerror(errno)); + } + + spice_channel_send_link(channel); + if (!spice_channel_recv_link_hdr(channel) || + !spice_channel_recv_link_msg(channel) || + !spice_channel_recv_auth(channel)) + goto cleanup; + + while (spice_channel_iterate(channel)) + ; + +cleanup: + CHANNEL_DEBUG(channel, "Coroutine exit %s", c->name); + + spice_channel_reset(channel, FALSE); + + if (c->state == SPICE_CHANNEL_STATE_RECONNECTING || + c->state == SPICE_CHANNEL_STATE_SWITCHING) { + g_warn_if_fail(c->event == SPICE_CHANNEL_NONE); + channel_connect(channel, c->tls); + g_object_unref(channel); + } else + g_idle_add(spice_channel_delayed_unref, data); + + /* Co-routine exits now - the SpiceChannel object may no longer exist, + so don't do anything else now unless you like SEGVs */ + return NULL; +} + +static gboolean connect_delayed(gpointer data) +{ + SpiceChannel *channel = data; + SpiceChannelPrivate *c = channel->priv; + struct coroutine *co; + + CHANNEL_DEBUG(channel, "Open coroutine starting %p", channel); + c->connect_delayed_id = 0; + + co = &c->coroutine.coroutine; + + co->stack_size = 16 << 20; /* 16Mb */ + co->entry = spice_channel_coroutine; + co->release = NULL; + + coroutine_init(co); + coroutine_yieldto(co, channel); + + return FALSE; +} + +/* any context */ +static gboolean channel_connect(SpiceChannel *channel, gboolean tls) +{ + SpiceChannelPrivate *c = channel->priv; + + g_return_val_if_fail(c != NULL, FALSE); + + if (c->session == NULL || c->channel_type == -1 || c->channel_id == -1) { + /* unset properties or unknown channel type */ + g_warning("%s: channel setup incomplete", __FUNCTION__); + return false; + } + + c->state = SPICE_CHANNEL_STATE_CONNECTING; + c->tls = tls; + + if (spice_session_get_client_provided_socket(c->session)) { + if (c->fd == -1) { + CHANNEL_DEBUG(channel, "requesting fd"); + /* FIXME: no way for client to provide fd atm. */ + /* It could either chain on parent channel.. */ + /* or register migration channel on parent session, or ? */ + g_signal_emit(channel, signals[SPICE_CHANNEL_OPEN_FD], 0, c->tls); + return true; + } + } + + c->xmit_queue_blocked = FALSE; + + g_return_val_if_fail(c->sock == NULL, FALSE); + g_object_ref(G_OBJECT(channel)); /* Unref'd when co-routine exits */ + + /* we connect in idle, to let previous coroutine exit, if present */ + c->connect_delayed_id = g_idle_add(connect_delayed, channel); + + return true; +} + +/** + * spice_channel_connect: + * @channel: a #SpiceChannel + * + * Connect the channel, using #SpiceSession connection informations + * + * Returns: %TRUE on success. + **/ +gboolean spice_channel_connect(SpiceChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_CHANNEL(channel), FALSE); + SpiceChannelPrivate *c = channel->priv; + + if (c->state >= SPICE_CHANNEL_STATE_CONNECTING) + return TRUE; + + g_return_val_if_fail(channel->priv->fd == -1, FALSE); + + return channel_connect(channel, FALSE); +} + +/** + * spice_channel_open_fd: + * @channel: a #SpiceChannel + * @fd: a file descriptor (socket) or -1. + * request mechanism + * + * Connect the channel using @fd socket. + * + * If @fd is -1, a valid fd will be requested later via the + * SpiceChannel::open-fd signal. + * + * Returns: %TRUE on success. + **/ +gboolean spice_channel_open_fd(SpiceChannel *channel, int fd) +{ + SpiceChannelPrivate *c; + + g_return_val_if_fail(SPICE_IS_CHANNEL(channel), FALSE); + g_return_val_if_fail(channel->priv != NULL, FALSE); + g_return_val_if_fail(channel->priv->fd == -1, FALSE); + g_return_val_if_fail(fd >= -1, FALSE); + + c = channel->priv; + if (c->state > SPICE_CHANNEL_STATE_CONNECTING) { + g_warning("Invalid channel_connect state: %u", c->state); + return true; + } + + c->fd = fd; + + return channel_connect(channel, FALSE); +} + +/* system or coroutine context */ +static void channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceChannelPrivate *c = channel->priv; + + CHANNEL_DEBUG(channel, "channel reset"); + if (c->connect_delayed_id) { + g_source_remove(c->connect_delayed_id); + c->connect_delayed_id = 0; + } + +#ifdef HAVE_SASL + if (c->sasl_conn) { + sasl_dispose(&c->sasl_conn); + c->sasl_conn = NULL; + c->sasl_decoded_offset = c->sasl_decoded_length = 0; + } +#endif + + g_clear_pointer(&c->sslverify, spice_openssl_verify_free); + g_clear_pointer(&c->ssl, SSL_free); + g_clear_pointer(&c->ctx, SSL_CTX_free); + + g_clear_object(&c->conn); + g_clear_object(&c->sock); + + c->fd = -1; + + c->auth_needs_username = FALSE; + c->auth_needs_password = FALSE; + + g_clear_pointer(&c->peer_msg, g_free); + c->peer_pos = 0; + + g_mutex_lock(&c->xmit_queue_lock); + c->xmit_queue_blocked = TRUE; /* Disallow queuing new messages */ + gboolean was_empty = g_queue_is_empty(&c->xmit_queue); + g_queue_foreach(&c->xmit_queue, (GFunc)spice_msg_out_unref, NULL); + g_queue_clear(&c->xmit_queue); + if (c->xmit_queue_wakeup_id) { + g_source_remove(c->xmit_queue_wakeup_id); + c->xmit_queue_wakeup_id = 0; + } + g_mutex_unlock(&c->xmit_queue_lock); + spice_channel_flushed(channel, was_empty); + + g_array_set_size(c->remote_common_caps, 0); + g_array_set_size(c->remote_caps, 0); + g_array_set_size(c->common_caps, 0); + /* Restore our default capabilities in case the channel gets re-used */ + spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION); + spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_MINI_HEADER); + spice_channel_reset_capabilities(channel); + + if (c->state == SPICE_CHANNEL_STATE_SWITCHING) + spice_session_set_migration_state(spice_channel_get_session(channel), + SPICE_SESSION_MIGRATION_NONE); +} + +/* system or coroutine context */ +G_GNUC_INTERNAL +void spice_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + CHANNEL_DEBUG(channel, "reset %s", migrating ? "migrating" : ""); + SPICE_CHANNEL_GET_CLASS(channel)->channel_reset(channel, migrating); +} + +/** + * spice_channel_disconnect: + * @channel: a #SpiceChannel + * @reason: a channel event emitted on main context (or #SPICE_CHANNEL_NONE) + * + * Close the socket and reset connection specific data. Finally, emit + * @reason #SpiceChannel::channel-event on main context if not + * #SPICE_CHANNEL_NONE. + **/ +void spice_channel_disconnect(SpiceChannel *channel, SpiceChannelEvent reason) +{ + SpiceChannelPrivate *c; + + CHANNEL_DEBUG(channel, "channel disconnect %u", reason); + + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + g_return_if_fail(channel->priv != NULL); + + c = channel->priv; + + if (c->state == SPICE_CHANNEL_STATE_UNCONNECTED) + return; + + if (reason == SPICE_CHANNEL_SWITCHING) + c->state = SPICE_CHANNEL_STATE_SWITCHING; + + c->has_error = TRUE; /* break the loop */ + + if (c->state == SPICE_CHANNEL_STATE_MIGRATING) { + c->state = SPICE_CHANNEL_STATE_READY; + } else + spice_channel_wakeup(channel, TRUE); + + if (reason != SPICE_CHANNEL_NONE) + g_signal_emit(G_OBJECT(channel), signals[SPICE_CHANNEL_EVENT], 0, reason); +} + +static gboolean test_capability(GArray *caps, guint32 cap) +{ + guint32 c, word_index = cap / 32; + gboolean ret; + + if (caps == NULL) + return FALSE; + + if (caps->len < word_index + 1) + return FALSE; + + c = g_array_index(caps, guint32, word_index); + ret = (c & (1 << (cap % 32))) != 0; + + SPICE_DEBUG("test cap %u in 0x%X: %s", cap, c, ret ? "yes" : "no"); + return ret; +} + +/** + * spice_channel_test_capability: + * @channel: a #SpiceChannel + * @cap: a capability + * + * Test availability of remote "channel kind capability". + * + * Returns: %TRUE if @cap (channel kind capability) is available. + **/ +gboolean spice_channel_test_capability(SpiceChannel *self, guint32 cap) +{ + SpiceChannelPrivate *c; + + g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE); + + c = self->priv; + return test_capability(c->remote_caps, cap); +} + +/** + * spice_channel_test_common_capability: + * @channel: a #SpiceChannel + * @cap: a capability + * + * Test availability of remote "common channel capability". + * + * Returns: %TRUE if @cap (common channel capability) is available. + **/ +gboolean spice_channel_test_common_capability(SpiceChannel *self, guint32 cap) +{ + SpiceChannelPrivate *c; + + g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE); + + c = self->priv; + return test_capability(c->remote_common_caps, cap); +} + +static void set_capability(GArray *caps, guint32 cap) +{ + guint word_index = cap / 32; + + g_return_if_fail(caps != NULL); + + if (caps->len <= word_index) + g_array_set_size(caps, word_index + 1); + + g_array_index(caps, guint32, word_index) = + g_array_index(caps, guint32, word_index) | (1 << (cap % 32)); +} + +/** + * spice_channel_set_capability: + * @channel: a #SpiceChannel + * @cap: a capability + * + * Enable specific channel-kind capability. + * Deprecated: 0.13: this function has been removed + **/ +#undef spice_channel_set_capability +void spice_channel_set_capability(SpiceChannel *channel, guint32 cap) +{ + SpiceChannelPrivate *c; + + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + + c = channel->priv; + set_capability(c->caps, cap); +} + +G_GNUC_INTERNAL +void spice_caps_set(GArray *caps, guint32 cap, const gchar *desc) +{ + g_return_if_fail(caps != NULL); + g_return_if_fail(desc != NULL); + + if (g_strcmp0(g_getenv(desc), "0") == 0) + return; + + set_capability(caps, cap); +} + +G_GNUC_INTERNAL +SpiceSession* spice_channel_get_session(SpiceChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_CHANNEL(channel), NULL); + + return channel->priv->session; +} + +G_GNUC_INTERNAL +enum spice_channel_state spice_channel_get_state(SpiceChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_CHANNEL(channel), + SPICE_CHANNEL_STATE_UNCONNECTED); + + return channel->priv->state; +} + +G_GNUC_INTERNAL +guint64 spice_channel_get_queue_size (SpiceChannel *channel) +{ + guint64 size; + SpiceChannelPrivate *c = channel->priv; + g_mutex_lock(&c->xmit_queue_lock); + size = c->xmit_queue_size; + g_mutex_unlock(&c->xmit_queue_lock); + return size; +} + +G_GNUC_INTERNAL +void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap_msgs) +{ + SpiceChannelPrivate *c = channel->priv; + SpiceChannelPrivate *s = swap->priv; + + g_return_if_fail(c != NULL); + g_return_if_fail(s != NULL); + + g_return_if_fail(s->session != NULL); + g_return_if_fail(s->sock != NULL); + +#define SWAP(Field) ({ \ + typeof (c->Field) Field = c->Field; \ + c->Field = s->Field; \ + s->Field = Field; \ +}) + + /* TODO: split channel in 2 objects: a controller and a swappable + state object */ + SWAP(sock); + SWAP(conn); + SWAP(in); + SWAP(out); + SWAP(ctx); + SWAP(ssl); + SWAP(sslverify); + SWAP(tls); + SWAP(use_mini_header); + if (swap_msgs) { + SWAP(xmit_queue); + SWAP(xmit_queue_blocked); + SWAP(in_serial); + SWAP(out_serial); + } + SWAP(caps); + SWAP(common_caps); + SWAP(remote_caps); + SWAP(remote_common_caps); +#ifdef HAVE_SASL + SWAP(sasl_conn); + SWAP(sasl_decoded); + SWAP(sasl_decoded_length); + SWAP(sasl_decoded_offset); +#endif +} + +/* coroutine context */ +static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg) +{ + SpiceChannelClass *klass = SPICE_CHANNEL_GET_CLASS(channel); + int type = spice_msg_in_type(msg); + spice_msg_handler handler; + + g_return_if_fail(type < klass->priv->handlers->len); + if (type > SPICE_MSG_BASE_LAST && channel->priv->disable_channel_msg) + return; + + handler = g_array_index(klass->priv->handlers, spice_msg_handler, type); + g_return_if_fail(handler != NULL); + handler(channel, msg); +} + +static void spice_channel_reset_capabilities(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + g_array_set_size(c->caps, 0); + + if (SPICE_CHANNEL_GET_CLASS(channel)->channel_reset_capabilities) { + SPICE_CHANNEL_GET_CLASS(channel)->channel_reset_capabilities(channel); + } +} + +static void spice_channel_send_migration_handshake(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = channel->priv; + + if (SPICE_CHANNEL_GET_CLASS(channel)->channel_send_migration_handshake) { + SPICE_CHANNEL_GET_CLASS(channel)->channel_send_migration_handshake(channel); + } else { + c->state = SPICE_CHANNEL_STATE_MIGRATING; + } +} + +/** + * spice_channel_flush_async: + * @channel: a #SpiceChannel + * @cancellable: (allow-none): optional GCancellable object, %NULL to ignore + * @callback: (scope async): callback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Forces an asynchronous write of all user-space buffered data for + * the given channel. + * + * When the operation is finished callback will be called. You can + * then call spice_channel_flush_finish() to get the result of the + * operation. + * + * Since: 0.15 + **/ +void spice_channel_flush_async(SpiceChannel *self, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) +{ + GTask *task; + SpiceChannelPrivate *c; + gboolean was_empty; + + g_return_if_fail(SPICE_IS_CHANNEL(self)); + c = self->priv; + + if (c->state != SPICE_CHANNEL_STATE_READY) { + g_task_report_new_error(self, callback, user_data, + spice_channel_flush_async, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "The channel is not ready yet"); + return; + } + + task = g_task_new(self, cancellable, callback, user_data); + + g_mutex_lock(&c->xmit_queue_lock); + was_empty = g_queue_is_empty(&c->xmit_queue); + g_mutex_unlock(&c->xmit_queue_lock); + if (was_empty) { + g_task_return_boolean(task, TRUE); + g_object_unref(task); + return; + } + + c->flushing = g_slist_append(c->flushing, task); +} + +/** + * spice_channel_flush_finish: + * @channel: a #SpiceChannel + * @result: a #GAsyncResult + * @error: a #GError location to store the error occurring, or %NULL + * to ignore. + * + * Finishes flushing a channel. + * + * Returns: %TRUE if flush operation succeeded, %FALSE otherwise. + * Since: 0.15 + **/ +gboolean spice_channel_flush_finish(SpiceChannel *self, GAsyncResult *result, + GError **error) +{ + GTask *task; + + g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE); + g_return_val_if_fail(result != NULL, FALSE); + + task = G_TASK(result); + + g_return_val_if_fail(g_task_is_valid(task, self), + FALSE); + + CHANNEL_DEBUG(self, "flushed finished!"); + return g_task_propagate_boolean(task, error); +} diff --git a/src/spice-channel.h b/src/spice-channel.h new file mode 100644 index 0000000..3b0bffb --- /dev/null +++ b/src/spice-channel.h @@ -0,0 +1,152 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_CHANNEL_H__ +#define __SPICE_CLIENT_CHANNEL_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include + +#include "spice-types.h" +#include "spice-glib-enums.h" +#include "spice-util.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_CHANNEL (spice_channel_get_type ()) +#define SPICE_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_CHANNEL, SpiceChannel)) +#define SPICE_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_CHANNEL, SpiceChannelClass)) +#define SPICE_IS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_CHANNEL)) +#define SPICE_IS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_CHANNEL)) +#define SPICE_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_CHANNEL, SpiceChannelClass)) + +typedef struct _SpiceMsgIn SpiceMsgIn; +typedef struct _SpiceMsgOut SpiceMsgOut; + +/** + * SpiceChannelEvent: + * @SPICE_CHANNEL_NONE: no event, or ignored event + * @SPICE_CHANNEL_OPENED: connection is authentified and ready + * @SPICE_CHANNEL_SWITCHING: disconnecting from the current host and connecting to the target host. + * @SPICE_CHANNEL_CLOSED: connection is closed normally (sent if channel was ready) + * @SPICE_CHANNEL_ERROR_CONNECT: connection error + * @SPICE_CHANNEL_ERROR_TLS: SSL error + * @SPICE_CHANNEL_ERROR_LINK: error during link process + * @SPICE_CHANNEL_ERROR_AUTH: authentication error + * @SPICE_CHANNEL_ERROR_IO: IO error + * + * An event, emitted by #SpiceChannel::channel-event signal. + **/ +typedef enum +{ + SPICE_CHANNEL_NONE = 0, + SPICE_CHANNEL_OPENED = 10, + SPICE_CHANNEL_SWITCHING, + SPICE_CHANNEL_CLOSED, + SPICE_CHANNEL_ERROR_CONNECT = 20, + SPICE_CHANNEL_ERROR_TLS, + SPICE_CHANNEL_ERROR_LINK, + SPICE_CHANNEL_ERROR_AUTH, + SPICE_CHANNEL_ERROR_IO, +} SpiceChannelEvent; + +/** + * SpiceChannel: + * + * The #SpiceChannel struct is opaque and should not be accessed directly. + */ +struct _SpiceChannel +{ + GObject parent; + SpiceChannelPrivate *priv; + /* Do not add fields to this struct */ +}; + +typedef struct _SpiceChannelClassPrivate SpiceChannelClassPrivate; + +/** + * SpiceChannelClass: + * @parent_class: Parent class. + * @channel_event: Signal class handler for the #SpiceChannel::channel_event signal. + * @open_fd: Signal class handler for the #SpiceChannel::open_fd signal. + * + * Class structure for #SpiceChannel. + */ +struct _SpiceChannelClass +{ + GObjectClass parent_class; + + /*< public >*/ + /* signals, main context */ + void (*channel_event)(SpiceChannel *channel, SpiceChannelEvent event); + void (*open_fd)(SpiceChannel *channel, int with_tls); + + /*< private >*/ + /* virtual methods, coroutine context */ + void (*handle_msg)(SpiceChannel *channel, SpiceMsgIn *msg); + void (*channel_up)(SpiceChannel *channel); + void (*iterate_write)(SpiceChannel *channel); + void (*iterate_read)(SpiceChannel *channel); + + /*< private >*/ + /* virtual method, any context */ + gpointer deprecated; + void (*channel_reset)(SpiceChannel *channel, gboolean migrating); + void (*channel_reset_capabilities)(SpiceChannel *channel); + + /*< private >*/ + /* virtual methods, coroutine context */ + void (*channel_send_migration_handshake)(SpiceChannel *channel); + + SpiceChannelClassPrivate *priv; + /* + * If adding fields to this struct, remove corresponding + * amount of padding to avoid changing overall struct size + */ + gchar _spice_reserved[SPICE_RESERVED_PADDING - 2 * sizeof(void *)]; +}; + +GType spice_channel_get_type(void); + +typedef void (*spice_msg_handler)(SpiceChannel *channel, SpiceMsgIn *in); + +SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id); +gboolean spice_channel_connect(SpiceChannel *channel); +gboolean spice_channel_open_fd(SpiceChannel *channel, int fd); +void spice_channel_disconnect(SpiceChannel *channel, SpiceChannelEvent reason); +gboolean spice_channel_test_capability(SpiceChannel *channel, guint32 cap); +gboolean spice_channel_test_common_capability(SpiceChannel *channel, guint32 cap); +void spice_channel_flush_async(SpiceChannel *channel, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +gboolean spice_channel_flush_finish(SpiceChannel *channel, GAsyncResult *result, GError **error); +#ifndef SPICE_DISABLE_DEPRECATED +SPICE_DEPRECATED +void spice_channel_set_capability(SpiceChannel *channel, guint32 cap); +SPICE_DEPRECATED +void spice_channel_destroy(SpiceChannel *channel); +#endif + +const gchar* spice_channel_type_to_string(gint type); +gint spice_channel_string_to_type(const gchar *str); + +const GError* spice_channel_get_error(SpiceChannel *channel); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_CHANNEL_H__ */ diff --git a/src/spice-client-glib-usb-acl-helper.c b/src/spice-client-glib-usb-acl-helper.c new file mode 100644 index 0000000..80cdced --- /dev/null +++ b/src/spice-client-glib-usb-acl-helper.c @@ -0,0 +1,363 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011,2012 Red Hat, Inc. + Copyright (C) 2009 Kay Sievers + + Red Hat Authors: + Hans de Goede + + 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, see . +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FATAL_ERROR(...) \ + do { \ + /* We print the error both to stdout, for the app invoking us and \ + stderr for the end user */ \ + fprintf(stdout, "Error " __VA_ARGS__); \ + fprintf(stderr, "spice-client-glib-usb-helper: Error " __VA_ARGS__); \ + exit_status = 1; \ + cleanup(); \ + } while (0) + +#define ERROR(...) \ + do { \ + fprintf(stdout, __VA_ARGS__); \ + cleanup(); \ + } while (0) + +enum state { + STATE_WAITING_FOR_BUS_N_DEV, + STATE_WAITING_FOR_POL_KIT, + STATE_WAITING_FOR_STDIN_EOF, +}; + +static enum state state = STATE_WAITING_FOR_BUS_N_DEV; +static int exit_status; +static int busnum, devnum; +static char path[PATH_MAX]; +static GMainLoop *loop; +static GDataInputStream *stdin_stream; +static GCancellable *polkit_cancellable; +static PolkitSubject *subject; +static PolkitAuthority *authority; + +/* + * This function is a copy of the same function in udev, written by Kay + * Sievers, you can find it in udev in extras/udev-acl/udev-acl.c + */ +static int set_facl(const char* filename, uid_t uid, int add) +{ + int get; + acl_t acl; + acl_entry_t entry = NULL; + acl_entry_t e; + acl_permset_t permset; + int ret; + + /* don't touch ACLs for root */ + if (uid == 0) + return 0; + + /* read current record */ + acl = acl_get_file(filename, ACL_TYPE_ACCESS); + if (!acl) + return -1; + + /* locate ACL_USER entry for uid */ + get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e); + while (get == 1) { + acl_tag_t t; + + acl_get_tag_type(e, &t); + if (t == ACL_USER) { + uid_t *u; + + u = (uid_t*)acl_get_qualifier(e); + if (u == NULL) { + ret = -1; + goto out; + } + if (*u == uid) { + entry = e; + acl_free(u); + break; + } + acl_free(u); + } + + get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e); + } + + /* remove ACL_USER entry for uid */ + if (!add) { + if (entry == NULL) { + ret = 0; + goto out; + } + acl_delete_entry(acl, entry); + goto update; + } + + /* create ACL_USER entry for uid */ + if (entry == NULL) { + ret = acl_create_entry(&acl, &entry); + if (ret != 0) + goto out; + acl_set_tag_type(entry, ACL_USER); + acl_set_qualifier(entry, &uid); + } + + /* add permissions for uid */ + acl_get_permset(entry, &permset); + acl_add_perm(permset, ACL_READ|ACL_WRITE); +update: + /* update record */ + acl_calc_mask(&acl); + ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl); + +out: + acl_free(acl); + return ret; +} + +static void cleanup(void) +{ + g_cancellable_cancel(polkit_cancellable); + + if (state == STATE_WAITING_FOR_STDIN_EOF) + set_facl(path, getuid(), 0); + + if (loop) + g_main_loop_quit(loop); +} + +/* Not available in polkit < 0.101 */ +#ifndef HAVE_POLKIT_AUTHORIZATION_RESULT_GET_DISMISSED +static gboolean +polkit_authorization_result_get_dismissed(PolkitAuthorizationResult *result) +{ + gboolean ret; + PolkitDetails *details; + + g_return_val_if_fail(POLKIT_IS_AUTHORIZATION_RESULT(result), FALSE); + + ret = FALSE; + details = polkit_authorization_result_get_details(result); + if (details != NULL && polkit_details_lookup(details, "polkit.dismissed")) + ret = TRUE; + + return ret; +} +#endif + +static void check_authorization_cb(PolkitAuthority *authority, + GAsyncResult *res, gpointer data) +{ + PolkitAuthorizationResult *result; + GError *err = NULL; + struct stat stat_buf; + + g_clear_object(&polkit_cancellable); + + result = polkit_authority_check_authorization_finish(authority, res, &err); + if (err) { + FATAL_ERROR("PoliciKit error: %s\n", err->message); + g_error_free(err); + return; + } + + if (polkit_authorization_result_get_dismissed(result)) { + ERROR("CANCELED\n"); + return; + } + + if (!polkit_authorization_result_get_is_authorized(result)) { + ERROR("Not authorized\n"); + return; + } + + snprintf(path, PATH_MAX, "/dev/bus/usb/%03d/%03d", busnum, devnum); + + if (stat(path, &stat_buf) != 0) { + FATAL_ERROR("statting %s: %s\n", path, strerror(errno)); + return; + } + if (!S_ISCHR(stat_buf.st_mode)) { + FATAL_ERROR("%s is not a character device\n", path); + return; + } + + if (set_facl(path, getuid(), 1)) { + FATAL_ERROR("setting facl: %s\n", strerror(errno)); + return; + } + + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + state = STATE_WAITING_FOR_STDIN_EOF; +} + +static void stdin_read_complete(GObject *src, GAsyncResult *res, gpointer data) +{ + char *s, *ep; + GError *err = NULL; + gsize len; + + s = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(src), res, + &len, &err); + if (!s) { + if (err) { + FATAL_ERROR("Reading from stdin: %s\n", err->message); + g_error_free(err); + return; + } + + switch (state) { + case STATE_WAITING_FOR_BUS_N_DEV: + FATAL_ERROR("EOF while waiting for bus and device num\n"); + break; + case STATE_WAITING_FOR_POL_KIT: + ERROR("Cancelled while waiting for authorization\n"); + break; + case STATE_WAITING_FOR_STDIN_EOF: + cleanup(); + break; + } + return; + } + + switch (state) { + case STATE_WAITING_FOR_BUS_N_DEV: + busnum = strtol(s, &ep, 10); + if (!isspace(*ep)) { + FATAL_ERROR("Invalid busnum / devnum: %s\n", s); + break; + } + devnum = strtol(ep, &ep, 10); + if (*ep != '\0') { + FATAL_ERROR("Invalid busnum / devnum: %s\n", s); + break; + } + + /* + * The set_facl() call is a no-op for root, so no need to ask PolKit + * and then if ok call set_facl(), when called by a root process. + */ + if (getuid() != 0) { + polkit_cancellable = g_cancellable_new(); + polkit_authority_check_authorization( + authority, subject, "org.spice-space.lowlevelusbaccess", NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + polkit_cancellable, + (GAsyncReadyCallback)check_authorization_cb, NULL); + state = STATE_WAITING_FOR_POL_KIT; + } else { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + state = STATE_WAITING_FOR_STDIN_EOF; + } + + g_data_input_stream_read_line_async(stdin_stream, G_PRIORITY_DEFAULT, + NULL, stdin_read_complete, NULL); + break; + default: + FATAL_ERROR("Unexpected extra input in state %u: %s\n", state, s); + } + g_free(s); +} + +/* Fix for polkit 0.97 and later */ +#ifndef HAVE_POLKIT_AUTHORITY_GET_SYNC +static PolkitAuthority * +polkit_authority_get_sync (GCancellable *cancellable, GError **error) +{ + PolkitAuthority *authority; + + authority = polkit_authority_get (); + if (!authority) + g_set_error (error, 0, 0, "failed to get the PolicyKit authority"); + + return authority; +} +#endif + +#ifndef HAVE_CLEARENV +extern char **environ; + +static int +clearenv (void) +{ + if (environ != NULL) + environ[0] = NULL; + return 0; +} +#endif + +int main(void) +{ + pid_t parent_pid; + GInputStream *stdin_unix_stream; + + /* Nuke the environment to get a well-known and sanitized + * environment to avoid attacks via e.g. the DBUS_SYSTEM_BUS_ADDRESS + * environment variable and similar. + */ + if (clearenv () != 0) { + FATAL_ERROR("Error clearing environment: %s\n", g_strerror (errno)); + return 1; + } + + loop = g_main_loop_new(NULL, FALSE); + + authority = polkit_authority_get_sync(NULL, NULL); + parent_pid = getppid (); + if (parent_pid == 1) { + FATAL_ERROR("Parent process was reaped by init(1)\n"); + return 1; + } + /* Do what pkexec does */ + subject = polkit_unix_process_new_for_owner(parent_pid, 0, getuid ()); + + stdin_unix_stream = g_unix_input_stream_new(STDIN_FILENO, 0); + stdin_stream = g_data_input_stream_new(stdin_unix_stream); + g_data_input_stream_set_newline_type(stdin_stream, + G_DATA_STREAM_NEWLINE_TYPE_LF); + g_clear_object(&stdin_unix_stream); + g_data_input_stream_read_line_async(stdin_stream, G_PRIORITY_DEFAULT, NULL, + stdin_read_complete, NULL); + + g_main_loop_run(loop); + + g_clear_object(&polkit_cancellable); + g_object_unref(stdin_stream); + g_object_unref(authority); + g_object_unref(subject); + g_main_loop_unref(loop); + + return exit_status; +} diff --git a/src/spice-client-gtk-manual.defs b/src/spice-client-gtk-manual.defs new file mode 100644 index 0000000..9631b74 --- /dev/null +++ b/src/spice-client-gtk-manual.defs @@ -0,0 +1,117 @@ +(define-method set_display + (of-object "SpiceMainChannel") + (c-name "spice_main_set_display") + (return-type "none") + (parameters + '("int" "id") + '("int" "x") + '("int" "y") + '("int" "width") + '("int" "height") + ) +) + +(define-method clipboard_grab + (of-object "SpiceMainChannel") + (c-name "spice_main_clipboard_grab") + (return-type "none") + (parameters + '("int*" "types") + '("int" "ntypes") + ) +) + +(define-method clipboard_release + (of-object "SpiceMainChannel") + (c-name "spice_main_clipboard_release") + (return-type "none") +) + +(define-method motion + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_motion") + (return-type "none") + (parameters + '("gint" "dx") + '("gint" "dy") + '("gint" "button_state") + ) +) + +(define-method position + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_position") + (return-type "none") + (parameters + '("gint" "x") + '("gint" "y") + '("gint" "display") + '("gint" "button_state") + ) +) + +(define-method button_press + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_button_press") + (return-type "none") + (parameters + '("gint" "button") + '("gint" "button_state") + ) +) + +(define-method button_release + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_button_release") + (return-type "none") + (parameters + '("gint" "button") + '("gint" "button_state") + ) +) + +(define-method key_press + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_key_press") + (return-type "none") + (parameters + '("guint" "keyval") + ) +) + +(define-method key_release + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_key_release") + (return-type "none") + (parameters + '("guint" "keyval") + ) +) + +(define-method set_key_locks + (of-object "SpiceInputsChannel") + (c-name "spice_inputs_set_key_locks") + (return-type "none") + (parameters + '("guint" "locks") + ) +) + +(define-enum ClientError + (in-module "Spice") + (c-name "SpiceClientError") + (values + '("failed" "SPICE_CLIENT_ERROR_FAILED") + ) +) + +(define-function spice_audio_new + (c-name "spice_audio_new") + (is-constructor-of "SpiceAudio") + (return-type "SpiceAudio*") + (parameters + '("SpiceSession*" "session") + '("GMainContext*" "context") + '("const-char*" "name") + ) +) diff --git a/src/spice-client-gtk.h b/src/spice-client-gtk.h new file mode 100644 index 0000000..0667145 --- /dev/null +++ b/src/spice-client-gtk.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_GTK_H__ +#define __SPICE_CLIENT_GTK_H__ + +#include "spice-client.h" + +#define __SPICE_CLIENT_GTK_H_INSIDE__ + +#include "spice-grabsequence.h" +#include "spice-gtk-session.h" +#include "spice-widget-enums.h" +#include "spice-widget.h" +#include "usb-device-widget.h" + +#undef __SPICE_CLIENT_GTK_H_INSIDE__ + +#endif /* __SPICE_CLIENT_GTK_H__ */ diff --git a/src/spice-client-gtk.override b/src/spice-client-gtk.override new file mode 100644 index 0000000..41aeee3 --- /dev/null +++ b/src/spice-client-gtk.override @@ -0,0 +1,171 @@ +%% +headers +#include +#include "pygobject.h" +#include "spice-common.h" +#include "spice-widget.h" +#include "spice-gtk-session.h" +#include "spice-audio.h" +#include "usb-device-widget.h" +%% +modulename spice_client_gtk +%% +import gobject.GObject as PyGObject_Type +import gtk.DrawingArea as PyGtkDrawingArea_Type +import gtk.Widget as PyGtkWidget_Type +import gtk.VBox as PyGtkVBox_Type +%% +ignore-glob + *_get_type +%% +%% +override spice_display_send_keys kwargs +static PyObject* +_wrap_spice_display_send_keys(PyGObject *self, + PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"keys", "kind", NULL}; + PyObject *keyList; + int kind = SPICE_DISPLAY_KEY_EVENT_CLICK; + int i, len; + guint *keys; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|I:SpiceDisplay.send_keys", kwlist, + &keyList, &kind)) + return NULL; + + if (!PyList_Check(keyList)) + return NULL; + + len = PyList_Size(keyList); + keys = g_malloc0(sizeof(guint)*len); + + for (i = 0 ; i < len ; i++) { + PyObject *val; + char *sym; + val = PyList_GetItem(keyList, i); + sym = PyString_AsString(val); + if (!sym) { + g_free(keys); + return NULL; + } + keys[i] = gdk_keyval_from_name(sym); + } + + spice_display_send_keys(SPICE_DISPLAY(self->obj), keys, len, kind); + g_free(keys); + + Py_INCREF(Py_None); + return Py_None; +} +%% +override spice_display_get_grab_keys kwargs +static PyObject* +_wrap_spice_display_get_grab_keys(PyGObject *self, + PyObject *args, PyObject *kwargs) +{ + SpiceGrabSequence *seq; + PyObject *keyList; + int i; + + seq = spice_display_get_grab_keys(SPICE_DISPLAY(self->obj)); + + keyList = PyList_New(0); + for (i = 0 ; i < seq->nkeysyms ; i++) + PyList_Append(keyList, PyInt_FromLong(seq->keysyms[i])); + + return keyList; +} +%% +override spice_display_set_grab_keys kwargs +static PyObject* +_wrap_spice_display_set_grab_keys(PyGObject *self, + PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"keys", NULL}; + PyObject *keyList; + int i; + guint nkeysyms; + guint *keysyms; + SpiceGrabSequence *seq; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|I:SpiceDisplay.set_grab_keys", kwlist, + &keyList)) + return NULL; + + if (!PyList_Check(keyList)) + return NULL; + + nkeysyms = PyList_Size(keyList); + keysyms = g_new0(guint, nkeysyms); + + for (i = 0 ; i < nkeysyms ; i++) { + PyObject *val = PyList_GetItem(keyList, i); + keysyms[i] = (guint)PyInt_AsLong(val); + } + + seq = spice_grab_sequence_new(nkeysyms, keysyms); + g_free(keysyms); + + spice_display_set_grab_keys(SPICE_DISPLAY(self->obj), seq); + + spice_grab_sequence_free(seq); + + Py_INCREF(Py_None); + return Py_None; +} +%% +override spice_session_get_channels +static PyObject* +_wrap_spice_session_get_channels(PyGObject *self, + PyObject *args, PyObject *kwargs) +{ + PyObject *py_list; + GList *list, *tmp; + PyObject *chann; + + list = spice_session_get_channels(SPICE_SESSION(self->obj)); + + if ((py_list = PyList_New(0)) == NULL) { + return NULL; + } + for (tmp = list; tmp != NULL; tmp = tmp->next) { + chann = pygobject_new(G_OBJECT(tmp->data)); + if (chann == NULL) { + Py_DECREF(py_list); + return NULL; + } + PyList_Append(py_list, chann); + Py_DECREF(chann); + } + return py_list; +} +%% +override spice_audio_new +static int +_wrap_spice_audio_new(PyGObject *self, + PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"session", "context", "name", NULL}; + PyGObject *session = NULL; + PyObject *py_context = NULL; + char *name = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|Os:SpiceAudio", kwlist, + &PySpiceSession_Type, &session, + &py_context, &name)) + return -1; + + self->obj = (GObject *)spice_audio_new(SPICE_SESSION(session->obj), NULL, NULL); + + if (!self->obj) { + PyErr_SetString(PyExc_RuntimeError, "could not create SpiceAudio object"); + return -1; + } + pygobject_register_wrapper((PyObject *)self); + return 0; + +} diff --git a/src/spice-client.c b/src/spice-client.c new file mode 100644 index 0000000..9f6412c --- /dev/null +++ b/src/spice-client.c @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include + +#include "spice-client.h" + +/** + * spice_client_error_quark: + * + * Gets a #GQuark representing the string "spice-client-error-quark" + * + * Returns: the #GQuark representing the string. + **/ +GQuark spice_client_error_quark(void) +{ + return g_quark_from_static_string("spice-client-error-quark"); +} diff --git a/src/spice-client.h b/src/spice-client.h new file mode 100644 index 0000000..32b79ea --- /dev/null +++ b/src/spice-client.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_CLIENT_H__ +#define __SPICE_CLIENT_CLIENT_H__ + +/* glib */ +#include +#include + +#define __SPICE_CLIENT_H_INSIDE__ + +/* spice-protocol */ +#include +#include + +/* spice/gtk */ +#include "spice-types.h" +#include "spice-session.h" +#include "spice-channel.h" +#include "spice-option.h" +#include "spice-uri.h" +#include "spice-version.h" + +#include "channel-main.h" +#include "channel-display.h" +#include "channel-cursor.h" +#include "channel-inputs.h" +#include "channel-playback.h" +#include "channel-record.h" +#include "channel-smartcard.h" +#include "channel-usbredir.h" +#include "channel-port.h" +#include "channel-webdav.h" + +#include "smartcard-manager.h" +#include "usb-device-manager.h" +#include "spice-audio.h" +#include "spice-file-transfer-task.h" + +G_BEGIN_DECLS + +/** + * SPICE_CLIENT_ERROR: + * + * Error domain for spice client errors. + */ +#define SPICE_CLIENT_ERROR spice_client_error_quark() + +/** + * SpiceClientError: + * @SPICE_CLIENT_ERROR_FAILED: generic error code + * @SPICE_CLIENT_ERROR_USB_DEVICE_REJECTED: device redirection rejected by host + * @SPICE_CLIENT_ERROR_USB_DEVICE_LOST: device disconnected (fatal IO error) + * @SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD: password is required + * @SPICE_CLIENT_ERROR_AUTH_NEEDS_USERNAME: username is required + * @SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME: password and username are required + * @SPICE_CLIENT_ERROR_USB_SERVICE: USB service error + * + * Error codes returned by spice-client API. + */ +typedef enum +{ + SPICE_CLIENT_ERROR_FAILED, + SPICE_CLIENT_ERROR_USB_DEVICE_REJECTED, + SPICE_CLIENT_ERROR_USB_DEVICE_LOST, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + SPICE_CLIENT_ERROR_AUTH_NEEDS_USERNAME, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME, + SPICE_CLIENT_ERROR_USB_SERVICE, +} SpiceClientError; + +#ifndef SPICE_DISABLE_DEPRECATED +#define SPICE_CLIENT_USB_DEVICE_REJECTED SPICE_CLIENT_ERROR_USB_DEVICE_REJECTED +#define SPICE_CLIENT_USB_DEVICE_LOST SPICE_CLIENT_ERROR_USB_DEVICE_LOST +#endif + +GQuark spice_client_error_quark(void); + +G_END_DECLS + +#undef __SPICE_CLIENT_H_INSIDE__ + +#endif /* __SPICE_CLIENT_CLIENT_H__ */ diff --git a/src/spice-cmdline.c b/src/spice-cmdline.c new file mode 100644 index 0000000..8619b57 --- /dev/null +++ b/src/spice-cmdline.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" +#include + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-cmdline.h" + +static char *host; +static char *port; +static char *tls_port; +static char *password; +static char *uri; + +static GOptionEntry spice_entries[] = { + { + .long_name = "uri", + .arg = G_OPTION_ARG_STRING, + .arg_data = &uri, + .description = N_("Spice server uri"), + .arg_description = N_(""), + },{ + .long_name = "host", + .short_name = 'h', + .arg = G_OPTION_ARG_STRING, + .arg_data = &host, + .description = N_("Spice server address"), + .arg_description = N_(""), + },{ + .long_name = "port", + .short_name = 'p', + .arg = G_OPTION_ARG_STRING, + .arg_data = &port, + .description = N_("Spice server port"), + .arg_description = N_(""), + },{ + .long_name = "secure-port", + .short_name = 's', + .arg = G_OPTION_ARG_STRING, + .arg_data = &tls_port, + .description = N_("Spice server secure port"), + .arg_description = N_(""), + },{ + .long_name = "password", + .short_name = 'w', + .arg = G_OPTION_ARG_STRING, + .arg_data = &password, + .description = N_("Server password"), + .arg_description = N_(""), + },{ + /* end of list */ + } +}; + +GOptionGroup *spice_cmdline_get_option_group(void) +{ + GOptionGroup *grp; + + grp = g_option_group_new("spice", + _("Spice connection options:"), + _("Show Spice options"), + NULL, NULL); + g_option_group_add_entries(grp, spice_entries); + + return grp; +} + +void spice_cmdline_session_setup(SpiceSession *session) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + if (uri) + g_object_set(session, "uri", uri, NULL); + if (host) + g_object_set(session, "host", host, NULL); + if (port) + g_object_set(session, "port", port, NULL); + if (tls_port) + g_object_set(session, "tls-port", tls_port, NULL); + if (password) + g_object_set(session, "password", password, NULL); +} diff --git a/src/spice-cmdline.h b/src/spice-cmdline.h new file mode 100644 index 0000000..11a8086 --- /dev/null +++ b/src/spice-cmdline.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef SPICE_CMDLINE_H_ +# define SPICE_CMDLINE_H_ + +G_BEGIN_DECLS + +GOptionGroup *spice_cmdline_get_option_group(void); +void spice_cmdline_session_setup(SpiceSession *session); + +G_END_DECLS + +#endif // SPICE_CMDLINE_H_ diff --git a/src/spice-common.h b/src/spice-common.h new file mode 100644 index 0000000..8554f4c --- /dev/null +++ b/src/spice-common.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICE_COMMON_H_ +# define SPICE_COMMON_H_ + +/* system */ +#include +#include +#include +#include +#include +#include +#include + +#include "common/mem.h" +#include "common/messages.h" +#include "common/marshaller.h" + +#include "spice-util.h" + +#endif // SPICE_COMMON_H_ diff --git a/src/spice-file-transfer-task.h b/src/spice-file-transfer-task.h new file mode 100644 index 0000000..4f179fb --- /dev/null +++ b/src/spice-file-transfer-task.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . + */ + +#ifndef __SPICE_FILE_TRANSFER_TASK_H__ +#define __SPICE_FILE_TRANSFER_TASK_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +#include + +G_BEGIN_DECLS + +#define SPICE_TYPE_FILE_TRANSFER_TASK spice_file_transfer_task_get_type() + +#define SPICE_FILE_TRANSFER_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_FILE_TRANSFER_TASK, SpiceFileTransferTask)) +#define SPICE_FILE_TRANSFER_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_FILE_TRANSFER_TASK, SpiceFileTransferTaskClass)) +#define SPICE_IS_FILE_TRANSFER_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_FILE_TRANSFER_TASK)) +#define SPICE_IS_FILE_TRANSFER_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_FILE_TRANSFER_TASK)) +#define SPICE_FILE_TRANSFER_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_FILE_TRANSFER_TASK, SpiceFileTransferTaskClass)) + +typedef struct _SpiceFileTransferTask SpiceFileTransferTask; +typedef struct _SpiceFileTransferTaskClass SpiceFileTransferTaskClass; + +GType spice_file_transfer_task_get_type(void) G_GNUC_CONST; + +char* spice_file_transfer_task_get_filename(SpiceFileTransferTask *self); +void spice_file_transfer_task_cancel(SpiceFileTransferTask *self); +double spice_file_transfer_task_get_progress(SpiceFileTransferTask *self); + +G_END_DECLS + +#endif /* __SPICE_FILE_TRANSFER_TASK_H__ */ diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file new file mode 100644 index 0000000..7d2af60 --- /dev/null +++ b/src/spice-glib-sym-file @@ -0,0 +1,125 @@ +spice_audio_get +spice_audio_get_type +spice_audio_new +spice_channel_connect +spice_channel_destroy +spice_channel_disconnect +spice_channel_event_get_type +spice_channel_flush_async +spice_channel_flush_finish +spice_channel_get_error +spice_channel_get_type +spice_channel_new +spice_channel_open_fd +spice_channel_set_capability +spice_channel_string_to_type +spice_channel_test_capability +spice_channel_test_common_capability +spice_channel_type_to_string +spice_client_error_quark +spice_cursor_channel_get_type +spice_display_change_preferred_compression +spice_display_channel_get_type +spice_display_get_gl_scanout +spice_display_get_primary +spice_display_gl_draw_done +spice_file_transfer_task_cancel +spice_file_transfer_task_get_filename +spice_file_transfer_task_get_progress +spice_file_transfer_task_get_type +spice_get_option_group +spice_gl_scanout_free +spice_gl_scanout_get_type +spice_g_signal_connect_object +spice_inputs_button_press +spice_inputs_button_release +spice_inputs_channel_get_type +spice_inputs_key_press +spice_inputs_key_press_and_release +spice_inputs_key_release +spice_inputs_lock_get_type +spice_inputs_motion +spice_inputs_position +spice_inputs_set_key_locks +spice_main_agent_test_capability +spice_main_channel_get_type +spice_main_clipboard_grab +spice_main_clipboard_notify +spice_main_clipboard_release +spice_main_clipboard_request +spice_main_clipboard_selection_grab +spice_main_clipboard_selection_notify +spice_main_clipboard_selection_release +spice_main_clipboard_selection_request +spice_main_file_copy_async +spice_main_file_copy_finish +spice_main_request_mouse_mode +spice_main_send_monitor_config +spice_main_set_display +spice_main_set_display_enabled +spice_main_update_display +spice_main_update_display_enabled +spice_playback_channel_get_type +spice_playback_channel_set_delay +spice_port_channel_get_type +spice_port_event +spice_port_write_async +spice_port_write_finish +spice_record_channel_get_type +spice_record_send_data +spice_session_connect +spice_session_disconnect +spice_session_get_channels +spice_session_get_proxy_uri +spice_session_get_read_only +spice_session_get_type +spice_session_has_channel_type +spice_session_is_for_migration +spice_session_migration_get_type +spice_session_new +spice_session_open_fd +spice_session_verify_get_type +spice_set_session_option +spice_smartcard_channel_get_type +spice_smartcard_manager_get +spice_smartcard_manager_get_readers +spice_smartcard_manager_get_type +spice_smartcard_manager_insert_card +spice_smartcard_manager_remove_card +spice_smartcard_reader_get_type +spice_smartcard_reader_insert_card +spice_smartcard_reader_is_software +spice_smartcard_reader_remove_card +spice_uri_get_hostname +spice_uri_get_password +spice_uri_get_port +spice_uri_get_scheme +spice_uri_get_type +spice_uri_get_user +spice_uri_set_hostname +spice_uri_set_password +spice_uri_set_port +spice_uri_set_scheme +spice_uri_set_user +spice_uri_to_string +spice_usb_device_get_description +spice_usb_device_get_libusb_device +spice_usb_device_get_type +spice_usb_device_manager_can_redirect_device +spice_usb_device_manager_connect_device_async +spice_usb_device_manager_connect_device_finish +spice_usb_device_manager_disconnect_device +spice_usb_device_manager_disconnect_device_async +spice_usb_device_manager_disconnect_device_finish +spice_usb_device_manager_get +spice_usb_device_manager_get_devices +spice_usb_device_manager_get_devices_with_filter +spice_usb_device_manager_get_type +spice_usb_device_manager_is_device_connected +spice_usb_device_manager_is_redirecting +spice_usbredir_channel_get_type +spice_util_get_debug +spice_util_get_version_string +spice_util_set_debug +spice_uuid_to_string +spice_webdav_channel_get_type diff --git a/src/spice-grabsequence-priv.h b/src/spice-grabsequence-priv.h new file mode 100644 index 0000000..97f05b2 --- /dev/null +++ b/src/spice-grabsequence-priv.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_GRABSEQUENCE_PRIV_H__ +#define __SPICE_GRABSEQUENCE_PRIV_H__ + +#include + +struct _SpiceGrabSequence { + /*< private >*/ + guint nkeysyms; + guint *keysyms; +}; + +#endif diff --git a/src/spice-grabsequence.c b/src/spice-grabsequence.c new file mode 100644 index 0000000..50e774d --- /dev/null +++ b/src/spice-grabsequence.c @@ -0,0 +1,171 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2010 Daniel P. Berrange + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include + +#include "spice-grabsequence.h" +#include "spice-grabsequence-priv.h" + +GType spice_grab_sequence_get_type(void) +{ + static GType grab_sequence_type = 0; + static volatile gsize grab_sequence_type_volatile; + + if (g_once_init_enter(&grab_sequence_type_volatile)) { + grab_sequence_type = g_boxed_type_register_static + ("SpiceGrabSequence", + (GBoxedCopyFunc)spice_grab_sequence_copy, + (GBoxedFreeFunc)spice_grab_sequence_free); + g_once_init_leave(&grab_sequence_type_volatile, + grab_sequence_type); + } + + return grab_sequence_type; +} + + +/** + * spice_grab_sequence_new: + * @nkeysyms: length of @keysyms + * @keysyms: (array length=nkeysyms): the keysym values + * + * Creates a new grab sequence from a list of keysym values + * + * Returns: (transfer full): a new grab sequence object + */ +SpiceGrabSequence *spice_grab_sequence_new(guint nkeysyms, guint *keysyms) +{ + SpiceGrabSequence *sequence; + + sequence = g_new0(SpiceGrabSequence, 1); + sequence->nkeysyms = nkeysyms; + sequence->keysyms = g_new0(guint, nkeysyms); + memcpy(sequence->keysyms, keysyms, sizeof(guint)*nkeysyms); + + return sequence; +} + + +/** + * spice_grab_sequence_new_from_string: + * @str: a string of '+' separated key names (ex: "Control_L+Alt_L") + * + * Creates a new #SpiceGrabSequence from the string representation. + * + * Returns: a new #SpiceGrabSequence. + **/ +SpiceGrabSequence *spice_grab_sequence_new_from_string(const gchar *str) +{ + gchar **keysymstr; + int i; + SpiceGrabSequence *sequence; + + sequence = g_new0(SpiceGrabSequence, 1); + + keysymstr = g_strsplit(str, "+", 5); + + sequence->nkeysyms = 0; + while (keysymstr[sequence->nkeysyms]) + sequence->nkeysyms++; + + sequence->keysyms = g_new0(guint, sequence->nkeysyms); + for (i = 0 ; i < sequence->nkeysyms ; i++) { + sequence->keysyms[i] = + (guint)gdk_keyval_from_name(keysymstr[i]); + if (sequence->keysyms[i] == 0) { + g_critical("Invalid key: %s", keysymstr[i]); + } + } + g_strfreev(keysymstr); + + return sequence; + +} + + +/** + * spice_grab_sequence_copy: + * @sequence: sequence to copy + * + * Creates a copy of the @sequence. + * + * Returns: (transfer full): a copy of @sequence + **/ +SpiceGrabSequence *spice_grab_sequence_copy(SpiceGrabSequence *srcSequence) +{ + SpiceGrabSequence *sequence; + + sequence = g_new0(SpiceGrabSequence, 1); + sequence->nkeysyms = srcSequence->nkeysyms; + sequence->keysyms = g_new0(guint, srcSequence->nkeysyms); + memcpy(sequence->keysyms, srcSequence->keysyms, + sizeof(guint) * sequence->nkeysyms); + + return sequence; +} + + +/** + * spice_grab_sequence_free: + * @sequence: a #SpiceGrabSequence + * + * Free @sequence. + **/ +void spice_grab_sequence_free(SpiceGrabSequence *sequence) +{ + g_free(sequence->keysyms); + g_free(sequence); +} + + +/** + * spice_grab_sequence_as_string: + * @sequence: a #SpiceGrabSequence + * + * Creates a string representing the @sequence. + * + * Returns: (transfer full): a newly allocated string representing the key sequence + **/ +gchar *spice_grab_sequence_as_string(SpiceGrabSequence *sequence) +{ + GString *str = g_string_new(""); + int i; + + for (i = 0 ; i < sequence->nkeysyms ; i++) { + if (i > 0) + g_string_append_c(str, '+'); + g_string_append(str, gdk_keyval_name(sequence->keysyms[i])); + } + + return g_string_free(str, FALSE); + +} + + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/spice-grabsequence.h b/src/spice-grabsequence.h new file mode 100644 index 0000000..7f61ba1 --- /dev/null +++ b/src/spice-grabsequence.h @@ -0,0 +1,62 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori + * Copyright (C) 2009-2010 Daniel P. Berrange + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SPICE_GRAB_SEQUENCE_H +#define SPICE_GRAB_SEQUENCE_H + +#if !defined(__SPICE_CLIENT_GTK_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include + +G_BEGIN_DECLS + +#define SPICE_TYPE_GRAB_SEQUENCE (spice_grab_sequence_get_type ()) + +/** + * SpiceGrabSequence: + * + * An opaque type that represents a grab sequence. + **/ +typedef struct _SpiceGrabSequence SpiceGrabSequence; + +GType spice_grab_sequence_get_type(void); + +SpiceGrabSequence *spice_grab_sequence_new(guint nkeysyms, guint *keysyms); +SpiceGrabSequence *spice_grab_sequence_new_from_string(const gchar *str); +SpiceGrabSequence *spice_grab_sequence_copy(SpiceGrabSequence *sequence); +void spice_grab_sequence_free(SpiceGrabSequence *sequence); +gchar *spice_grab_sequence_as_string(SpiceGrabSequence *sequence); + + +G_END_DECLS + +#endif /* SPICE_GRAB_SEQUENCE_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c new file mode 100644 index 0000000..1d96c77 --- /dev/null +++ b/src/spice-gstaudio.c @@ -0,0 +1,715 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#include +#include + +#include "spice-gstaudio.h" +#include "spice-common.h" +#include "spice-session.h" +#include "spice-util.h" + +#define SPICE_GSTAUDIO_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_GSTAUDIO, SpiceGstaudioPrivate)) + +G_DEFINE_TYPE(SpiceGstaudio, spice_gstaudio, SPICE_TYPE_AUDIO) + +struct stream { + GstElement *pipe; + GstElement *src; + GstElement *sink; + guint rate; + guint channels; +}; + +struct _SpiceGstaudioPrivate { + SpiceChannel *pchannel; + SpiceChannel *rchannel; + struct stream playback; + struct stream record; + guint mmtime_id; +}; + +static gboolean connect_channel(SpiceAudio *audio, SpiceChannel *channel); +static void channel_weak_notified(gpointer data, GObject *where_the_object_was); +static void spice_gstaudio_get_playback_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, gpointer user_data); +static gboolean spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); +static void spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, gpointer user_data); +static gboolean spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); + +static void spice_gstaudio_finalize(GObject *obj) +{ + G_OBJECT_CLASS(spice_gstaudio_parent_class)->finalize(obj); +} + +static void stream_dispose(struct stream *s) +{ + if (s->pipe) { + gst_element_set_state(s->pipe, GST_STATE_NULL); + g_clear_pointer(&s->pipe, gst_object_unref); + } + + g_clear_pointer(&s->src, gst_object_unref); + g_clear_pointer(&s->sink, gst_object_unref); +} + +static void spice_gstaudio_dispose(GObject *obj) +{ + SpiceGstaudio *gstaudio = SPICE_GSTAUDIO(obj); + SpiceGstaudioPrivate *p; + SPICE_DEBUG("%s", __FUNCTION__); + p = gstaudio->priv; + + stream_dispose(&p->playback); + stream_dispose(&p->record); + + if (p->pchannel) + g_object_weak_unref(G_OBJECT(p->pchannel), channel_weak_notified, gstaudio); + p->pchannel = NULL; + + if (p->rchannel) + g_object_weak_unref(G_OBJECT(p->rchannel), channel_weak_notified, gstaudio); + p->rchannel = NULL; + + if (G_OBJECT_CLASS(spice_gstaudio_parent_class)->dispose) + G_OBJECT_CLASS(spice_gstaudio_parent_class)->dispose(obj); +} + +static void spice_gstaudio_init(SpiceGstaudio *gstaudio) +{ + gstaudio->priv = SPICE_GSTAUDIO_GET_PRIVATE(gstaudio); +} + +static void spice_gstaudio_class_init(SpiceGstaudioClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceAudioClass *audio_class = SPICE_AUDIO_CLASS(klass); + + audio_class->connect_channel = connect_channel; + audio_class->get_playback_volume_info_async = spice_gstaudio_get_playback_volume_info_async; + audio_class->get_playback_volume_info_finish = spice_gstaudio_get_playback_volume_info_finish; + audio_class->get_record_volume_info_async = spice_gstaudio_get_record_volume_info_async; + audio_class->get_record_volume_info_finish = spice_gstaudio_get_record_volume_info_finish; + + gobject_class->finalize = spice_gstaudio_finalize; + gobject_class->dispose = spice_gstaudio_dispose; + + g_type_class_add_private(klass, sizeof(SpiceGstaudioPrivate)); +} + +static GstFlowReturn record_new_buffer(GstAppSink *appsink, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstMessage *msg; + + g_return_val_if_fail(p != NULL, GST_FLOW_ERROR); + + msg = gst_message_new_application(GST_OBJECT(p->record.pipe), + gst_structure_new_empty ("new-sample")); + gst_element_post_message(p->record.pipe, msg); + return GST_FLOW_OK; +} + +static void record_stop(SpiceGstaudio *gstaudio) +{ + SpiceGstaudioPrivate *p = gstaudio->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + if (p->record.pipe) + gst_element_set_state(p->record.pipe, GST_STATE_READY); +} + +static gboolean record_bus_cb(GstBus *bus, GstMessage *msg, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + + g_return_val_if_fail(p != NULL, FALSE); + + switch (GST_MESSAGE_TYPE(msg)) { + case GST_MESSAGE_APPLICATION: { + GstSample *s; + GstBuffer *buffer; + GstMapInfo mapping; + + s = gst_app_sink_pull_sample(GST_APP_SINK(p->record.sink)); + if (!s) { + if (!gst_app_sink_is_eos(GST_APP_SINK(p->record.sink))) + g_warning("eos not reached, but can't pull new sample"); + return TRUE; + } + + buffer = gst_sample_get_buffer(s); + if (!buffer) { + if (!gst_app_sink_is_eos(GST_APP_SINK(p->record.sink))) + g_warning("eos not reached, but can't pull new buffer"); + return TRUE; + } + if (!gst_buffer_map(buffer, &mapping, GST_MAP_READ)) { + return TRUE; + } + + spice_record_send_data(SPICE_RECORD_CHANNEL(p->rchannel), + /* FIXME: server side doesn't care about ts? + what is the unit? ms apparently */ + mapping.data, mapping.size, 0); + gst_buffer_unmap(buffer, &mapping); + gst_sample_unref(s); + break; + } + default: + break; + } + + return TRUE; +} + +static void record_start(SpiceRecordChannel *channel, gint format, gint channels, + gint frequency, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + + g_return_if_fail(p != NULL); + g_return_if_fail(format == SPICE_AUDIO_FMT_S16); + + if (p->record.pipe && + (p->record.rate != frequency || + p->record.channels != channels)) { + record_stop(gstaudio); + g_clear_pointer(&p->record.pipe, gst_object_unref); + } + + if (!p->record.pipe) { + GError *error = NULL; + GstBus *bus; + gchar *audio_caps = + g_strdup_printf("audio/x-raw,format=\"S16LE\",channels=%d,rate=%d," + "layout=interleaved", channels, frequency); + gchar *pipeline = + g_strdup_printf("autoaudiosrc name=audiosrc ! queue ! audioconvert ! audioresample ! " + "appsink caps=\"%s\" name=appsink", audio_caps); + + p->record.pipe = gst_parse_launch(pipeline, &error); + if (error != NULL) { + g_warning("Failed to create pipeline: %s", error->message); + goto cleanup; + } + + bus = gst_pipeline_get_bus(GST_PIPELINE(p->record.pipe)); + gst_bus_add_watch(bus, record_bus_cb, data); + gst_object_unref(GST_OBJECT(bus)); + + p->record.src = gst_bin_get_by_name(GST_BIN(p->record.pipe), "audiosrc"); + p->record.sink = gst_bin_get_by_name(GST_BIN(p->record.pipe), "appsink"); + p->record.rate = frequency; + p->record.channels = channels; + + gst_app_sink_set_emit_signals(GST_APP_SINK(p->record.sink), TRUE); + spice_g_signal_connect_object(p->record.sink, "new-sample", + G_CALLBACK(record_new_buffer), gstaudio, 0); + +cleanup: + if (error != NULL) + g_clear_pointer(&p->record.pipe, gst_object_unref); + g_clear_error(&error); + g_free(audio_caps); + g_free(pipeline); + } + + if (p->record.pipe) + gst_element_set_state(p->record.pipe, GST_STATE_PLAYING); +} + +static void playback_stop(SpiceGstaudio *gstaudio) +{ + SpiceGstaudioPrivate *p = gstaudio->priv; + + if (p->playback.pipe) + gst_element_set_state(p->playback.pipe, GST_STATE_READY); + if (p->mmtime_id != 0) { + g_source_remove(p->mmtime_id); + p->mmtime_id = 0; + } +} + +static gboolean update_mmtime_timeout_cb(gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstQuery *q; + + q = gst_query_new_latency(); + if (gst_element_query(p->playback.pipe, q)) { + gboolean live; + GstClockTime minlat, maxlat; + gst_query_parse_latency(q, &live, &minlat, &maxlat); + SPICE_DEBUG("got min latency %" GST_TIME_FORMAT ", max latency %" + GST_TIME_FORMAT ", live %d", GST_TIME_ARGS (minlat), + GST_TIME_ARGS (maxlat), live); + spice_playback_channel_set_delay(SPICE_PLAYBACK_CHANNEL(p->pchannel), GST_TIME_AS_MSECONDS(minlat)); + } + gst_query_unref (q); + + return TRUE; +} + +static void playback_start(SpicePlaybackChannel *channel, gint format, gint channels, + gint frequency, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + + g_return_if_fail(p != NULL); + g_return_if_fail(format == SPICE_AUDIO_FMT_S16); + + if (p->playback.pipe && + (p->playback.rate != frequency || + p->playback.channels != channels)) { + playback_stop(gstaudio); + g_clear_pointer(&p->playback.pipe, gst_object_unref); + } + + if (!p->playback.pipe) { + GError *error = NULL; + gchar *audio_caps = + g_strdup_printf("audio/x-raw,format=\"S16LE\",channels=%d,rate=%d," + "layout=interleaved", channels, frequency); + gchar *pipeline = g_strdup (g_getenv("SPICE_GST_AUDIOSINK")); + if (pipeline == NULL) + pipeline = g_strdup_printf("appsrc is-live=1 do-timestamp=0 caps=\"%s\" name=\"appsrc\" ! queue ! " + "audioconvert ! audioresample ! autoaudiosink name=\"audiosink\"", audio_caps); + SPICE_DEBUG("audio pipeline: %s", pipeline); + p->playback.pipe = gst_parse_launch(pipeline, &error); + if (error != NULL) { + g_warning("Failed to create pipeline: %s", error->message); + goto cleanup; + } + p->playback.src = gst_bin_get_by_name(GST_BIN(p->playback.pipe), "appsrc"); + p->playback.sink = gst_bin_get_by_name(GST_BIN(p->playback.pipe), "audiosink"); + p->playback.rate = frequency; + p->playback.channels = channels; + +cleanup: + if (error != NULL) + g_clear_pointer(&p->playback.pipe, gst_object_unref); + g_clear_error(&error); + g_free(audio_caps); + g_free(pipeline); + } + + if (p->playback.pipe) + gst_element_set_state(p->playback.pipe, GST_STATE_PLAYING); + + if (p->mmtime_id == 0) { + update_mmtime_timeout_cb(gstaudio); + p->mmtime_id = g_timeout_add_seconds(1, update_mmtime_timeout_cb, gstaudio); + } +} + +static void playback_data(SpicePlaybackChannel *channel, + gpointer *audio, gint size, + gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstBuffer *buf; + + g_return_if_fail(p != NULL); + + audio = g_memdup(audio, size); /* TODO: try to avoid memory copy */ + buf = gst_buffer_new_wrapped(audio, size); + gst_app_src_push_buffer(GST_APP_SRC(p->playback.src), buf); +} + +#define VOLUME_NORMAL 65535 + +static void playback_volume_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + GstElement *e; + guint16 *volume; + guint nchannels; + SpiceGstaudioPrivate *p = gstaudio->priv; + gdouble vol; + + if (!p->playback.sink) + return; + + g_object_get(object, + "volume", &volume, + "nchannels", &nchannels, + NULL); + + g_return_if_fail(nchannels > 0); + + vol = 1.0 * volume[0] / VOLUME_NORMAL; + SPICE_DEBUG("playback volume changed to %u (%0.2f)", volume[0], 100*vol); + + if (GST_IS_BIN(p->playback.sink)) + e = gst_bin_get_by_interface(GST_BIN(p->playback.sink), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->playback.sink); + + if (GST_IS_STREAM_VOLUME(e)) + gst_stream_volume_set_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC, vol); + else + g_object_set(e, "volume", vol, NULL); + + g_object_unref(e); +} + +static void playback_mute_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstElement *e; + gboolean mute; + + if (!p->playback.sink) + return; + + g_object_get(object, "mute", &mute, NULL); + SPICE_DEBUG("playback mute changed to %d", mute); + + if (GST_IS_BIN(p->playback.sink)) + e = gst_bin_get_by_interface(GST_BIN(p->playback.sink), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->playback.sink); + + if (GST_IS_STREAM_VOLUME(e)) + gst_stream_volume_set_mute(GST_STREAM_VOLUME(e), mute); + + g_object_unref(e); +} + +static void record_volume_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstElement *e; + guint16 *volume; + guint nchannels; + gdouble vol; + + if (!p->record.src) + return; + + g_object_get(object, + "volume", &volume, + "nchannels", &nchannels, + NULL); + + g_return_if_fail(nchannels > 0); + + vol = 1.0 * volume[0] / VOLUME_NORMAL; + SPICE_DEBUG("record volume changed to %u (%0.2f)", volume[0], 100*vol); + + /* TODO directsoundsrc doesn't support IDirectSoundBuffer_SetVolume */ + /* TODO pulsesrc doesn't support volume property, it's all coming! */ + + if (GST_IS_BIN(p->record.src)) + e = gst_bin_get_by_interface(GST_BIN(p->record.src), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->record.src); + + if (GST_IS_STREAM_VOLUME(e)) + gst_stream_volume_set_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC, vol); + else + g_warning("gst lacks volume capabilities on src (TODO)"); + + g_object_unref(e); +} + +static void record_mute_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpiceGstaudio *gstaudio = data; + SpiceGstaudioPrivate *p = gstaudio->priv; + GstElement *e; + gboolean mute; + + if (!p->record.src) + return; + + g_object_get(object, "mute", &mute, NULL); + SPICE_DEBUG("record mute changed to %d", mute); + + if (GST_IS_BIN(p->record.src)) + e = gst_bin_get_by_interface(GST_BIN(p->record.src), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->record.src); + + if (GST_IS_STREAM_VOLUME (e)) + gst_stream_volume_set_mute(GST_STREAM_VOLUME(e), mute); + else + g_warning("gst lacks mute capabilities on src: %d (TODO)", mute); + + g_object_unref(e); +} + +static void +channel_weak_notified(gpointer data, + GObject *where_the_object_was) +{ + SpiceGstaudio *gstaudio = SPICE_GSTAUDIO(data); + SpiceGstaudioPrivate *p = gstaudio->priv; + + if (where_the_object_was == (GObject *)p->pchannel) { + SPICE_DEBUG("playback closed"); + playback_stop(gstaudio); + p->pchannel = NULL; + } else if (where_the_object_was == (GObject *)p->rchannel) { + SPICE_DEBUG("record closed"); + record_stop(gstaudio); + p->rchannel = NULL; + } +} + +static gboolean connect_channel(SpiceAudio *audio, SpiceChannel *channel) +{ + SpiceGstaudio *gstaudio = SPICE_GSTAUDIO(audio); + SpiceGstaudioPrivate *p = gstaudio->priv; + + if (SPICE_IS_PLAYBACK_CHANNEL(channel)) { + g_return_val_if_fail(p->pchannel == NULL, FALSE); + + p->pchannel = channel; + g_object_weak_ref(G_OBJECT(p->pchannel), channel_weak_notified, audio); + spice_g_signal_connect_object(channel, "playback-start", + G_CALLBACK(playback_start), gstaudio, 0); + spice_g_signal_connect_object(channel, "playback-data", + G_CALLBACK(playback_data), gstaudio, 0); + spice_g_signal_connect_object(channel, "playback-stop", + G_CALLBACK(playback_stop), gstaudio, G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "notify::volume", + G_CALLBACK(playback_volume_changed), gstaudio, 0); + spice_g_signal_connect_object(channel, "notify::mute", + G_CALLBACK(playback_mute_changed), gstaudio, 0); + + return TRUE; + } + + if (SPICE_IS_RECORD_CHANNEL(channel)) { + g_return_val_if_fail(p->rchannel == NULL, FALSE); + + p->rchannel = channel; + g_object_weak_ref(G_OBJECT(p->rchannel), channel_weak_notified, audio); + spice_g_signal_connect_object(channel, "record-start", + G_CALLBACK(record_start), gstaudio, 0); + spice_g_signal_connect_object(channel, "record-stop", + G_CALLBACK(record_stop), gstaudio, G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "notify::volume", + G_CALLBACK(record_volume_changed), gstaudio, 0); + spice_g_signal_connect_object(channel, "notify::mute", + G_CALLBACK(record_mute_changed), gstaudio, 0); + + return TRUE; + } + + return FALSE; +} + +SpiceGstaudio *spice_gstaudio_new(SpiceSession *session, GMainContext *context, + const char *name) +{ + GError *err = NULL; + if (gst_init_check(NULL, NULL, &err)) { + return g_object_new(SPICE_TYPE_GSTAUDIO, + "session", session, + "main-context", context, + NULL); + } + + g_warning("Disabling GStreamer audio support: %s", err->message); + g_clear_error(&err); + return NULL; +} + +static void spice_gstaudio_get_playback_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task = g_task_new(audio, cancellable, callback, user_data); + + g_task_return_boolean(task, TRUE); +} + +static gboolean spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + SpiceGstaudioPrivate *p = SPICE_GSTAUDIO(audio)->priv; + GstElement *e; + gboolean lmute; + gdouble vol; + gboolean fake_channel = FALSE; + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, audio), FALSE); + + if (g_task_had_error(task)) { + /* set out args that should have new alloc'ed memory to NULL */ + if (volume != NULL) { + *volume = NULL; + } + return g_task_propagate_boolean(task, error); + } + + if (p->playback.sink == NULL || p->playback.channels == 0) { + SPICE_DEBUG("PlaybackChannel not created yet, force start"); + /* In order to get system volume, we start the pipeline */ + playback_start(NULL, SPICE_AUDIO_FMT_S16, 2, 48000, audio); + fake_channel = TRUE; + } + + if (GST_IS_BIN(p->playback.sink)) + e = gst_bin_get_by_interface(GST_BIN(p->playback.sink), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->playback.sink); + + if (GST_IS_STREAM_VOLUME(e)) { + vol = gst_stream_volume_get_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC); + lmute = gst_stream_volume_get_mute(GST_STREAM_VOLUME(e)); + } else { + g_object_get(e, + "volume", &vol, + "mute", &lmute, NULL); + } + g_object_unref(e); + + if (fake_channel) { + SPICE_DEBUG("Stop faked PlaybackChannel"); + playback_stop(SPICE_GSTAUDIO(audio)); + } + + if (mute != NULL) { + *mute = lmute; + } + + if (nchannels != NULL) { + *nchannels = p->playback.channels; + } + + if (volume != NULL) { + gint i; + *volume = g_new(guint16, p->playback.channels); + for (i = 0; i < p->playback.channels; i++) { + (*volume)[i] = (guint16) (vol * VOLUME_NORMAL); + SPICE_DEBUG("(playback) volume at %d is %u (%0.2f%%)", i, (*volume)[i], 100*vol); + } + } + + return g_task_propagate_boolean(task, error); +} + +static void spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task = g_task_new(audio, cancellable, callback, user_data); + + g_task_return_boolean(task, TRUE); +} + +static gboolean spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + SpiceGstaudioPrivate *p = SPICE_GSTAUDIO(audio)->priv; + GstElement *e; + gboolean lmute; + gdouble vol; + gboolean fake_channel = FALSE; + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, audio), FALSE); + + if (g_task_had_error(task)) { + /* set out args that should have new alloc'ed memory to NULL */ + if (volume != NULL) { + *volume = NULL; + } + return g_task_propagate_boolean(task, error); + } + + if (p->record.src == NULL || p->record.channels == 0) { + SPICE_DEBUG("RecordChannel not created yet, force start"); + /* In order to get system volume, we start the pipeline */ + record_start(NULL, SPICE_AUDIO_FMT_S16, 2, 48000, audio); + fake_channel = TRUE; + } + + if (GST_IS_BIN(p->record.src)) + e = gst_bin_get_by_interface(GST_BIN(p->record.src), GST_TYPE_STREAM_VOLUME); + else + e = g_object_ref(p->record.src); + + if (GST_IS_STREAM_VOLUME(e)) { + vol = gst_stream_volume_get_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC); + lmute = gst_stream_volume_get_mute(GST_STREAM_VOLUME(e)); + } else { + g_object_get(e, + "volume", &vol, + "mute", &lmute, NULL); + } + g_object_unref(e); + + if (fake_channel) { + SPICE_DEBUG("Stop faked RecordChannel"); + record_stop(SPICE_GSTAUDIO(audio)); + } + + if (mute != NULL) { + *mute = lmute; + } + + if (nchannels != NULL) { + *nchannels = p->record.channels; + } + + if (volume != NULL) { + gint i; + *volume = g_new(guint16, p->record.channels); + for (i = 0; i < p->record.channels; i++) { + (*volume)[i] = (guint16) (vol * VOLUME_NORMAL); + SPICE_DEBUG("(record) volume at %d is %u (%0.2f%%)", i, (*volume)[i], 100*vol); + } + } + + return g_task_propagate_boolean(task, error); +} diff --git a/src/spice-gstaudio.h b/src/spice-gstaudio.h new file mode 100644 index 0000000..b605f1c --- /dev/null +++ b/src/spice-gstaudio.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_GSTAUDIO_H__ +#define __SPICE_CLIENT_GSTAUDIO_H__ + +#include "spice-client.h" +#include "spice-audio.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_GSTAUDIO (spice_gstaudio_get_type()) +#define SPICE_GSTAUDIO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_GSTAUDIO, SpiceGstaudio)) +#define SPICE_GSTAUDIO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_GSTAUDIO, SpiceGstaudioClass)) +#define SPICE_IS_GSTAUDIO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_GSTAUDIO)) +#define SPICE_IS_GSTAUDIO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_GSTAUDIO)) +#define SPICE_GSTAUDIO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_GSTAUDIO, SpiceGstaudioClass)) + + +typedef struct _SpiceGstaudio SpiceGstaudio; +typedef struct _SpiceGstaudioClass SpiceGstaudioClass; +typedef struct _SpiceGstaudioPrivate SpiceGstaudioPrivate; + +struct _SpiceGstaudio { + SpiceAudio parent; + SpiceGstaudioPrivate *priv; + /* Do not add fields to this struct */ +}; + +struct _SpiceGstaudioClass { + SpiceAudioClass parent_class; + /* Do not add fields to this struct */ +}; + +GType spice_gstaudio_get_type(void); + +SpiceGstaudio *spice_gstaudio_new(SpiceSession *session, + GMainContext *context, const char *name); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_GSTAUDIO_H__ */ diff --git a/src/spice-gtk-session-priv.h b/src/spice-gtk-session-priv.h new file mode 100644 index 0000000..d7fe313 --- /dev/null +++ b/src/spice-gtk-session-priv.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_GTK_SESSION_PRIV_H__ +#define __SPICE_CLIENT_GTK_SESSION_PRIV_H__ + +#include "spice-gtk-session.h" + +G_BEGIN_DECLS + +typedef struct _SpiceGtkSessionPrivate SpiceGtkSessionPrivate; + +struct _SpiceGtkSession +{ + GObject parent; + SpiceGtkSessionPrivate *priv; +}; + +struct _SpiceGtkSessionClass +{ + GObjectClass parent_class; +}; + +void spice_gtk_session_request_auto_usbredir(SpiceGtkSession *self, + gboolean state); +gboolean spice_gtk_session_get_read_only(SpiceGtkSession *self); +void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self); +void spice_gtk_session_set_pointer_grabbed(SpiceGtkSession *self, gboolean grabbed); +gboolean spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self); +void spice_gtk_session_set_keyboard_has_focus(SpiceGtkSession *self, gboolean keyboard_has_focus); +void spice_gtk_session_set_mouse_has_pointer(SpiceGtkSession *self, gboolean mouse_has_pointer); +gboolean spice_gtk_session_get_keyboard_has_focus(SpiceGtkSession *self); +gboolean spice_gtk_session_get_mouse_has_pointer(SpiceGtkSession *self); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_GTK_SESSION_PRIV_H__ */ diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c new file mode 100644 index 0000000..6cdae87 --- /dev/null +++ b/src/spice-gtk-session.c @@ -0,0 +1,1291 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include + +#ifdef HAVE_X11_XKBLIB_H +#include +#include +#endif +#ifdef GDK_WINDOWING_X11 +#include +#include +#endif +#ifdef G_OS_WIN32 +#include +#include +#ifndef MAPVK_VK_TO_VSC /* may be undefined in older mingw-headers */ +#define MAPVK_VK_TO_VSC 0 +#endif +#endif + +#include +#include +#include "desktop-integration.h" +#include "spice-common.h" +#include "spice-gtk-session.h" +#include "spice-gtk-session-priv.h" +#include "spice-session-priv.h" +#include "spice-util-priv.h" +#include "spice-channel-priv.h" + +#define CLIPBOARD_LAST (VD_AGENT_CLIPBOARD_SELECTION_SECONDARY + 1) + +struct _SpiceGtkSessionPrivate { + SpiceSession *session; + /* Clipboard related */ + gboolean auto_clipboard_enable; + SpiceMainChannel *main; + GtkClipboard *clipboard; + GtkClipboard *clipboard_primary; + GtkTargetEntry *clip_targets[CLIPBOARD_LAST]; + guint nclip_targets[CLIPBOARD_LAST]; + gboolean clip_hasdata[CLIPBOARD_LAST]; + gboolean clip_grabbed[CLIPBOARD_LAST]; + gboolean clipboard_by_guest[CLIPBOARD_LAST]; + /* auto-usbredir related */ + gboolean auto_usbredir_enable; + int auto_usbredir_reqs; + gboolean pointer_grabbed; + gboolean keyboard_has_focus; + gboolean mouse_has_pointer; + gboolean sync_modifiers; +}; + +/** + * SECTION:spice-gtk-session + * @short_description: handles GTK connection details + * @title: Spice GTK Session + * @section_id: + * @see_also: #SpiceSession, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client-gtk.h + * + * The #SpiceGtkSession class is the spice-client-gtk counter part of + * #SpiceSession. It contains functionality which should be handled per + * session rather then per #SpiceDisplay (one session can have multiple + * displays), but which cannot live in #SpiceSession as it depends on + * GTK. For example the clipboard functionality. + * + * There should always be a 1:1 relation between #SpiceGtkSession objects + * and #SpiceSession objects. Therefor there is no spice_gtk_session_new, + * instead there is spice_gtk_session_get() which ensures this 1:1 relation. + * + * Client and guest clipboards will be shared automatically if + * #SpiceGtkSession:auto-clipboard is set to #TRUE. Alternatively, you + * can send / receive clipboard data from client to guest with + * spice_gtk_session_copy_to_guest() / spice_gtk_session_paste_from_guest(). + */ + +/* ------------------------------------------------------------------ */ +/* Prototypes for private functions */ +static void clipboard_owner_change(GtkClipboard *clipboard, + GdkEventOwnerChange *event, + gpointer user_data); +static void channel_new(SpiceSession *session, SpiceChannel *channel, + gpointer user_data); +static void channel_destroy(SpiceSession *session, SpiceChannel *channel, + gpointer user_data); +static gboolean read_only(SpiceGtkSession *self); + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_GTK_SESSION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_GTK_SESSION, SpiceGtkSessionPrivate)) + +G_DEFINE_TYPE (SpiceGtkSession, spice_gtk_session, G_TYPE_OBJECT); + +/* Properties */ +enum { + PROP_0, + PROP_SESSION, + PROP_AUTO_CLIPBOARD, + PROP_AUTO_USBREDIR, + PROP_POINTER_GRABBED, + PROP_SYNC_MODIFIERS, +}; + +static guint32 get_keyboard_lock_modifiers(void) +{ + guint32 modifiers = 0; +#if GTK_CHECK_VERSION(3,18,0) + GdkKeymap *keyboard = gdk_keymap_get_default(); + + if (gdk_keymap_get_caps_lock_state(keyboard)) { + modifiers |= SPICE_INPUTS_CAPS_LOCK; + } + + if (gdk_keymap_get_num_lock_state(keyboard)) { + modifiers |= SPICE_INPUTS_NUM_LOCK; + } + + if (gdk_keymap_get_scroll_lock_state(keyboard)) { + modifiers |= SPICE_INPUTS_SCROLL_LOCK; + } +#else +#ifdef HAVE_X11_XKBLIB_H + Display *x_display = NULL; + XKeyboardState keyboard_state; + + GdkScreen *screen = gdk_screen_get_default(); + if (!GDK_IS_X11_DISPLAY(gdk_screen_get_display(screen))) { + SPICE_DEBUG("FIXME: gtk backend is not X11"); + return 0; + } + + x_display = GDK_SCREEN_XDISPLAY(screen); + XGetKeyboardControl(x_display, &keyboard_state); + + if (keyboard_state.led_mask & 0x01) { + modifiers |= SPICE_INPUTS_CAPS_LOCK; + } + if (keyboard_state.led_mask & 0x02) { + modifiers |= SPICE_INPUTS_NUM_LOCK; + } + if (keyboard_state.led_mask & 0x04) { + modifiers |= SPICE_INPUTS_SCROLL_LOCK; + } +#elif defined(G_OS_WIN32) + if (GetKeyState(VK_CAPITAL) & 1) { + modifiers |= SPICE_INPUTS_CAPS_LOCK; + } + if (GetKeyState(VK_NUMLOCK) & 1) { + modifiers |= SPICE_INPUTS_NUM_LOCK; + } + if (GetKeyState(VK_SCROLL) & 1) { + modifiers |= SPICE_INPUTS_SCROLL_LOCK; + } +#else + g_warning("get_keyboard_lock_modifiers not implemented"); +#endif // HAVE_X11_XKBLIB_H +#endif // GTK_CHECK_VERSION(3,18,0) + return modifiers; +} + +static void spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSession *self, + SpiceInputsChannel* inputs, + gboolean force) +{ + guint32 guest_modifiers = 0, client_modifiers = 0; + + g_return_if_fail(SPICE_IS_INPUTS_CHANNEL(inputs)); + + if (SPICE_IS_GTK_SESSION(self) && !self->priv->sync_modifiers) { + SPICE_DEBUG("Syncing modifiers is disabled"); + return; + } + + g_object_get(inputs, "key-modifiers", &guest_modifiers, NULL); + client_modifiers = get_keyboard_lock_modifiers(); + + if (force || client_modifiers != guest_modifiers) { + CHANNEL_DEBUG(inputs, "client_modifiers:0x%x, guest_modifiers:0x%x", + client_modifiers, guest_modifiers); + spice_inputs_set_key_locks(inputs, client_modifiers); + } +} + +static void keymap_modifiers_changed(GdkKeymap *keymap, gpointer data) +{ + SpiceGtkSession *self = data; + + spice_gtk_session_sync_keyboard_modifiers(self); +} + +static void guest_modifiers_changed(SpiceInputsChannel *inputs, gpointer data) +{ + SpiceGtkSession *self = data; + + spice_gtk_session_sync_keyboard_modifiers_for_channel(self, inputs, FALSE); +} + +static void spice_gtk_session_init(SpiceGtkSession *self) +{ + SpiceGtkSessionPrivate *s; + GdkKeymap *keymap = gdk_keymap_get_default(); + + s = self->priv = SPICE_GTK_SESSION_GET_PRIVATE(self); + + s->clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + g_signal_connect(G_OBJECT(s->clipboard), "owner-change", + G_CALLBACK(clipboard_owner_change), self); + s->clipboard_primary = gtk_clipboard_get(GDK_SELECTION_PRIMARY); + g_signal_connect(G_OBJECT(s->clipboard_primary), "owner-change", + G_CALLBACK(clipboard_owner_change), self); + spice_g_signal_connect_object(keymap, "state-changed", + G_CALLBACK(keymap_modifiers_changed), self, 0); +} + +static GObject * +spice_gtk_session_constructor(GType gtype, + guint n_properties, + GObjectConstructParam *properties) +{ + GObject *obj; + SpiceGtkSession *self; + SpiceGtkSessionPrivate *s; + GList *list; + GList *it; + + { + /* Always chain up to the parent constructor */ + GObjectClass *parent_class; + parent_class = G_OBJECT_CLASS(spice_gtk_session_parent_class); + obj = parent_class->constructor(gtype, n_properties, properties); + } + + self = SPICE_GTK_SESSION(obj); + s = self->priv; + if (!s->session) + g_error("SpiceGtKSession constructed without a session"); + + g_signal_connect(s->session, "channel-new", + G_CALLBACK(channel_new), self); + g_signal_connect(s->session, "channel-destroy", + G_CALLBACK(channel_destroy), self); + list = spice_session_get_channels(s->session); + for (it = g_list_first(list); it != NULL; it = g_list_next(it)) { + channel_new(s->session, it->data, (gpointer*)self); + } + g_list_free(list); + + return obj; +} + +static void spice_gtk_session_dispose(GObject *gobject) +{ + SpiceGtkSession *self = SPICE_GTK_SESSION(gobject); + SpiceGtkSessionPrivate *s = self->priv; + + /* release stuff */ + if (s->clipboard) { + g_signal_handlers_disconnect_by_func(s->clipboard, + G_CALLBACK(clipboard_owner_change), self); + s->clipboard = NULL; + } + + if (s->clipboard_primary) { + g_signal_handlers_disconnect_by_func(s->clipboard_primary, + G_CALLBACK(clipboard_owner_change), self); + s->clipboard_primary = NULL; + } + + if (s->session) { + g_signal_handlers_disconnect_by_func(s->session, + G_CALLBACK(channel_new), + self); + g_signal_handlers_disconnect_by_func(s->session, + G_CALLBACK(channel_destroy), + self); + s->session = NULL; + } + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_gtk_session_parent_class)->dispose) + G_OBJECT_CLASS(spice_gtk_session_parent_class)->dispose(gobject); +} + +static void spice_gtk_session_finalize(GObject *gobject) +{ + SpiceGtkSession *self = SPICE_GTK_SESSION(gobject); + SpiceGtkSessionPrivate *s = self->priv; + int i; + + /* release stuff */ + for (i = 0; i < CLIPBOARD_LAST; ++i) { + g_clear_pointer(&s->clip_targets[i], g_free); + } + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_gtk_session_parent_class)->finalize) + G_OBJECT_CLASS(spice_gtk_session_parent_class)->finalize(gobject); +} + +static void spice_gtk_session_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceGtkSession *self = SPICE_GTK_SESSION(gobject); + SpiceGtkSessionPrivate *s = self->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, s->session); + break; + case PROP_AUTO_CLIPBOARD: + g_value_set_boolean(value, s->auto_clipboard_enable); + break; + case PROP_AUTO_USBREDIR: + g_value_set_boolean(value, s->auto_usbredir_enable); + break; + case PROP_POINTER_GRABBED: + g_value_set_boolean(value, s->pointer_grabbed); + break; + case PROP_SYNC_MODIFIERS: + g_value_set_boolean(value, s->sync_modifiers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_gtk_session_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceGtkSession *self = SPICE_GTK_SESSION(gobject); + SpiceGtkSessionPrivate *s = self->priv; + + switch (prop_id) { + case PROP_SESSION: + s->session = g_value_get_object(value); + break; + case PROP_AUTO_CLIPBOARD: + s->auto_clipboard_enable = g_value_get_boolean(value); + break; + case PROP_AUTO_USBREDIR: { + SpiceDesktopIntegration *desktop_int; + gboolean orig_value = s->auto_usbredir_enable; + + s->auto_usbredir_enable = g_value_get_boolean(value); + if (s->auto_usbredir_enable == orig_value) + break; + + if (s->auto_usbredir_reqs) { + SpiceUsbDeviceManager *manager = + spice_usb_device_manager_get(s->session, NULL); + + if (!manager) + break; + + g_object_set(manager, "auto-connect", s->auto_usbredir_enable, + NULL); + + desktop_int = spice_desktop_integration_get(s->session); + if (s->auto_usbredir_enable) + spice_desktop_integration_inhibit_automount(desktop_int); + else + spice_desktop_integration_uninhibit_automount(desktop_int); + } + break; + } + case PROP_SYNC_MODIFIERS: + s->sync_modifiers = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_gtk_session_class_init(SpiceGtkSessionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->constructor = spice_gtk_session_constructor; + gobject_class->dispose = spice_gtk_session_dispose; + gobject_class->finalize = spice_gtk_session_finalize; + gobject_class->get_property = spice_gtk_session_get_property; + gobject_class->set_property = spice_gtk_session_set_property; + + /** + * SpiceGtkSession:session: + * + * #SpiceSession this #SpiceGtkSession is associated with + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_SESSION, + g_param_spec_object("session", + "Session", + "SpiceSession", + SPICE_TYPE_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceGtkSession:auto-clipboard: + * + * When this is true the clipboard gets automatically shared between host + * and guest. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_AUTO_CLIPBOARD, + g_param_spec_boolean("auto-clipboard", + "Auto clipboard", + "Automatically relay clipboard changes between " + "host and guest.", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceGtkSession:auto-usbredir: + * + * Automatically redirect newly plugged in USB devices. Note the auto + * redirection only happens when a #SpiceDisplay associated with the + * session had keyboard focus. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_AUTO_USBREDIR, + g_param_spec_boolean("auto-usbredir", + "Auto USB Redirection", + "Automatically redirect newly plugged in USB" + "Devices to the guest.", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceGtkSession:pointer-grabbed: + * + * Returns %TRUE if the pointer is currently grabbed by this session. + * + * Since: 0.27 + **/ + g_object_class_install_property + (gobject_class, PROP_POINTER_GRABBED, + g_param_spec_boolean("pointer-grabbed", + "Pointer grabbed", + "Whether the pointer is grabbed", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceGtkSession:sync-modifiers: + * + * Automatically sync modifiers (Caps, Num and Scroll locks) with the guest. + * + * Since: 0.32 + **/ + g_object_class_install_property + (gobject_class, PROP_SYNC_MODIFIERS, + g_param_spec_boolean("sync-modifiers", + "Sync modifiers", + "Automatically sync modifiers", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private(klass, sizeof(SpiceGtkSessionPrivate)); +} + +/* ---------------------------------------------------------------- */ +/* private functions (clipboard related) */ + +static GtkClipboard* get_clipboard_from_selection(SpiceGtkSessionPrivate *s, + guint selection) +{ + if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) { + return s->clipboard; + } else if (selection == VD_AGENT_CLIPBOARD_SELECTION_PRIMARY) { + return s->clipboard_primary; + } else { + g_warning("Unhandled clipboard selection: %u", selection); + return NULL; + } +} + +static gint get_selection_from_clipboard(SpiceGtkSessionPrivate *s, + GtkClipboard* cb) +{ + if (cb == s->clipboard) { + return VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + } else if (cb == s->clipboard_primary) { + return VD_AGENT_CLIPBOARD_SELECTION_PRIMARY; + } else { + g_warning("Unhandled clipboard"); + return -1; + } +} + +static const struct { + const char *xatom; + uint32_t vdagent; +} atom2agent[] = { + { + .vdagent = VD_AGENT_CLIPBOARD_UTF8_TEXT, + .xatom = "UTF8_STRING", + },{ + .vdagent = VD_AGENT_CLIPBOARD_UTF8_TEXT, + .xatom = "text/plain;charset=utf-8" + },{ + .vdagent = VD_AGENT_CLIPBOARD_UTF8_TEXT, + .xatom = "STRING" + },{ + .vdagent = VD_AGENT_CLIPBOARD_UTF8_TEXT, + .xatom = "TEXT" + },{ + .vdagent = VD_AGENT_CLIPBOARD_UTF8_TEXT, + .xatom = "text/plain" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_PNG, + .xatom = "image/png" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_BMP, + .xatom = "image/bmp" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_BMP, + .xatom = "image/x-bmp" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_BMP, + .xatom = "image/x-MS-bmp" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_BMP, + .xatom = "image/x-win-bitmap" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_TIFF, + .xatom = "image/tiff" + },{ + .vdagent = VD_AGENT_CLIPBOARD_IMAGE_JPG, + .xatom = "image/jpeg" + } +}; + +typedef struct _WeakRef { + GObject *object; +} WeakRef; + +static void weak_notify_cb(WeakRef *weakref, GObject *object) +{ + weakref->object = NULL; +} + +static WeakRef* weak_ref(GObject *object) +{ + WeakRef *weakref = g_new(WeakRef, 1); + + g_object_weak_ref(object, (GWeakNotify)weak_notify_cb, weakref); + weakref->object = object; + + return weakref; +} + +static void weak_unref(WeakRef* weakref) +{ + if (weakref->object) + g_object_weak_unref(weakref->object, (GWeakNotify)weak_notify_cb, weakref); + + g_free(weakref); +} + +static void clipboard_get_targets(GtkClipboard *clipboard, + GdkAtom *atoms, + gint n_atoms, + gpointer user_data) +{ + WeakRef *weakref = user_data; + SpiceGtkSession *self = (SpiceGtkSession*)weakref->object; + weak_unref(weakref); + + if (self == NULL) + return; + + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + + SpiceGtkSessionPrivate *s = self->priv; + guint32 types[SPICE_N_ELEMENTS(atom2agent)]; + char *name; + int a, m, t; + int selection; + + if (s->main == NULL) + return; + + selection = get_selection_from_clipboard(s, clipboard); + g_return_if_fail(selection != -1); + + SPICE_DEBUG("%s:", __FUNCTION__); + if (spice_util_get_debug()) { + for (a = 0; a < n_atoms; a++) { + name = gdk_atom_name(atoms[a]); + SPICE_DEBUG(" \"%s\"", name); + g_free(name); + } + } + + memset(types, 0, sizeof(types)); + for (a = 0; a < n_atoms; a++) { + name = gdk_atom_name(atoms[a]); + for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) { + if (strcasecmp(name, atom2agent[m].xatom) != 0) { + continue; + } + /* found match */ + for (t = 0; t < SPICE_N_ELEMENTS(atom2agent); t++) { + if (types[t] == atom2agent[m].vdagent) { + /* type already in list */ + break; + } + if (types[t] == 0) { + /* add type to empty slot */ + types[t] = atom2agent[m].vdagent; + break; + } + } + break; + } + g_free(name); + } + for (t = 0; t < SPICE_N_ELEMENTS(atom2agent); t++) { + if (types[t] == 0) { + break; + } + } + if (!s->clip_grabbed[selection] && t > 0) { + s->clip_grabbed[selection] = TRUE; + + if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) + spice_main_clipboard_selection_grab(s->main, selection, types, t); + /* Sending a grab causes the agent to do an impicit release */ + s->nclip_targets[selection] = 0; + } +} + +static void clipboard_owner_change(GtkClipboard *clipboard, + GdkEventOwnerChange *event, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + int selection; + + selection = get_selection_from_clipboard(s, clipboard); + g_return_if_fail(selection != -1); + + if (s->main == NULL) + return; + + if (s->clip_grabbed[selection]) { + s->clip_grabbed[selection] = FALSE; + if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) + spice_main_clipboard_selection_release(s->main, selection); + } + + switch (event->reason) { + case GDK_OWNER_CHANGE_NEW_OWNER: + if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(self)) + break; + + s->clipboard_by_guest[selection] = FALSE; + s->clip_hasdata[selection] = TRUE; + if (s->auto_clipboard_enable && !read_only(self)) + gtk_clipboard_request_targets(clipboard, clipboard_get_targets, + weak_ref(G_OBJECT(self))); + break; + default: + s->clip_hasdata[selection] = FALSE; + break; + } +} + +typedef struct +{ + SpiceGtkSession *self; + GMainLoop *loop; + GtkSelectionData *selection_data; + guint info; + guint selection; +} RunInfo; + +static void clipboard_got_from_guest(SpiceMainChannel *main, guint selection, + guint type, const guchar *data, guint size, + gpointer user_data) +{ + RunInfo *ri = user_data; + SpiceGtkSessionPrivate *s = ri->self->priv; + gchar *conv = NULL; + + g_return_if_fail(selection == ri->selection); + + SPICE_DEBUG("clipboard got data"); + + if (atom2agent[ri->info].vdagent == VD_AGENT_CLIPBOARD_UTF8_TEXT) { + /* on windows, gtk+ would already convert to LF endings, but + not on unix */ + if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_GUEST_LINEEND_CRLF)) { + GError *err = NULL; + + conv = spice_dos2unix((gchar*)data, size, &err); + if (err) { + g_warning("Failed to convert text line ending: %s", err->message); + g_clear_error(&err); + goto end; + } + + size = strlen(conv); + } + + gtk_selection_data_set_text(ri->selection_data, conv ?: (gchar*)data, size); + } else { + gtk_selection_data_set(ri->selection_data, + gdk_atom_intern_static_string(atom2agent[ri->info].xatom), + 8, data, size); + } + +end: + if (g_main_loop_is_running (ri->loop)) + g_main_loop_quit (ri->loop); + + g_free(conv); +} + +static void clipboard_agent_connected(RunInfo *ri) +{ + g_warning("agent status changed, cancel clipboard request"); + + if (g_main_loop_is_running(ri->loop)) + g_main_loop_quit(ri->loop); +} + +static void clipboard_get(GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, gpointer user_data) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); + + RunInfo ri = { NULL, }; + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + gboolean agent_connected = FALSE; + gulong clipboard_handler; + gulong agent_handler; + int selection; + + SPICE_DEBUG("clipboard get"); + + selection = get_selection_from_clipboard(s, clipboard); + g_return_if_fail(selection != -1); + g_return_if_fail(info < SPICE_N_ELEMENTS(atom2agent)); + g_return_if_fail(s->main != NULL); + + ri.selection_data = selection_data; + ri.info = info; + ri.loop = g_main_loop_new(NULL, FALSE); + ri.selection = selection; + ri.self = self; + + clipboard_handler = g_signal_connect(s->main, "main-clipboard-selection", + G_CALLBACK(clipboard_got_from_guest), + &ri); + agent_handler = g_signal_connect_swapped(s->main, "notify::agent-connected", + G_CALLBACK(clipboard_agent_connected), + &ri); + + spice_main_clipboard_selection_request(s->main, selection, + atom2agent[info].vdagent); + + + g_object_get(s->main, "agent-connected", &agent_connected, NULL); + if (!agent_connected) { + SPICE_DEBUG("canceled clipboard_get, before running loop"); + goto cleanup; + } + + /* apparently, this is needed to avoid dead-lock, from + gtk_dialog_run */ + gdk_threads_leave(); + g_main_loop_run(ri.loop); + gdk_threads_enter(); + +cleanup: + g_clear_pointer(&ri.loop, g_main_loop_unref); + g_signal_handler_disconnect(s->main, clipboard_handler); + g_signal_handler_disconnect(s->main, agent_handler); +} + +static void clipboard_clear(GtkClipboard *clipboard, gpointer user_data) +{ + SPICE_DEBUG("clipboard_clear"); + /* We watch for clipboard ownership changes and act on those, so we + don't need to do anything here */ +} + +static gboolean clipboard_grab(SpiceMainChannel *main, guint selection, + guint32* types, guint32 ntypes, + gpointer user_data) +{ + g_return_val_if_fail(SPICE_IS_GTK_SESSION(user_data), FALSE); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + GtkTargetEntry targets[SPICE_N_ELEMENTS(atom2agent)]; + gboolean target_selected[SPICE_N_ELEMENTS(atom2agent)] = { FALSE, }; + gboolean found; + GtkClipboard* cb; + int m, n, i; + + cb = get_clipboard_from_selection(s, selection); + g_return_val_if_fail(cb != NULL, FALSE); + + i = 0; + for (n = 0; n < ntypes; ++n) { + found = FALSE; + for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) { + if (atom2agent[m].vdagent == types[n] && !target_selected[m]) { + found = TRUE; + g_return_val_if_fail(i < SPICE_N_ELEMENTS(atom2agent), FALSE); + targets[i].target = (gchar*)atom2agent[m].xatom; + targets[i].info = m; + target_selected[m] = TRUE; + i += 1; + } + } + if (!found) { + g_warning("clipboard: couldn't find a matching type for: %u", + types[n]); + } + } + + g_free(s->clip_targets[selection]); + s->nclip_targets[selection] = i; + s->clip_targets[selection] = g_memdup(targets, sizeof(GtkTargetEntry) * i); + /* Receiving a grab implies we've released our own grab */ + s->clip_grabbed[selection] = FALSE; + + if (read_only(self) || + !s->auto_clipboard_enable || + s->nclip_targets[selection] == 0) + goto skip_grab_clipboard; + + if (!gtk_clipboard_set_with_owner(cb, targets, i, + clipboard_get, clipboard_clear, G_OBJECT(self))) { + g_warning("clipboard grab failed"); + return FALSE; + } + s->clipboard_by_guest[selection] = TRUE; + s->clip_hasdata[selection] = FALSE; + +skip_grab_clipboard: + return TRUE; +} + +static gboolean check_clipboard_size_limits(SpiceGtkSession *session, + gint clipboard_len) +{ + int max_clipboard; + + g_object_get(session->priv->main, "max-clipboard", &max_clipboard, NULL); + if (max_clipboard != -1 && clipboard_len > max_clipboard) { + g_warning("discarded clipboard of size %d (max: %d)", + clipboard_len, max_clipboard); + return FALSE; + } else if (clipboard_len <= 0) { + SPICE_DEBUG("discarding empty clipboard"); + return FALSE; + } + + return TRUE; +} + +static void clipboard_received_cb(GtkClipboard *clipboard, + GtkSelectionData *selection_data, + gpointer user_data) +{ + WeakRef *weakref = user_data; + SpiceGtkSession *self = (SpiceGtkSession*)weakref->object; + weak_unref(weakref); + + if (self == NULL) + return; + + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + + SpiceGtkSessionPrivate *s = self->priv; + gint len = 0, m; + guint32 type = VD_AGENT_CLIPBOARD_NONE; + gchar* name; + GdkAtom atom; + int selection; + + selection = get_selection_from_clipboard(s, clipboard); + g_return_if_fail(selection != -1); + + len = gtk_selection_data_get_length(selection_data); + if (!check_clipboard_size_limits(self, len)) { + return; + } else { + atom = gtk_selection_data_get_data_type(selection_data); + name = gdk_atom_name(atom); + for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) { + if (strcasecmp(name, atom2agent[m].xatom) == 0) { + break; + } + } + + if (m >= SPICE_N_ELEMENTS(atom2agent)) { + g_warning("clipboard_received for unsupported type: %s", name); + } else { + type = atom2agent[m].vdagent; + } + + g_free(name); + } + + const guchar *data = gtk_selection_data_get_data(selection_data); + gpointer conv = NULL; + + /* gtk+ internal utf8 newline is always LF, even on windows */ + if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) { + if (spice_main_agent_test_capability(s->main, VD_AGENT_CAP_GUEST_LINEEND_CRLF)) { + GError *err = NULL; + + conv = spice_unix2dos((gchar*)data, len, &err); + if (err) { + g_warning("Failed to convert text line ending: %s", err->message); + g_clear_error(&err); + return; + } + + len = strlen(conv); + } else { + /* On Windows, with some versions of gtk+, GtkSelectionData::length + * will include the final '\0'. When a string with this trailing '\0' + * is pasted in some linux applications, it will be pasted as or + * as an invisible character, which is unwanted. Ensure the length we + * send to the agent does not include any trailing '\0' + * This is gtk+ bug https://bugzilla.gnome.org/show_bug.cgi?id=734670 + */ + len = strlen((const char *)data); + } + if (!check_clipboard_size_limits(self, len)) { + g_free(conv); + return; + } + } + + spice_main_clipboard_selection_notify(s->main, selection, type, + conv ?: data, len); + g_free(conv); +} + +static gboolean clipboard_request(SpiceMainChannel *main, guint selection, + guint type, gpointer user_data) +{ + g_return_val_if_fail(SPICE_IS_GTK_SESSION(user_data), FALSE); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + GdkAtom atom; + GtkClipboard* cb; + int m; + + g_return_val_if_fail(s->clipboard_by_guest[selection] == FALSE, FALSE); + g_return_val_if_fail(s->clip_grabbed[selection], FALSE); + + if (read_only(self)) + return FALSE; + + cb = get_clipboard_from_selection(s, selection); + g_return_val_if_fail(cb != NULL, FALSE); + + for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) { + if (atom2agent[m].vdagent == type) + break; + } + + g_return_val_if_fail(m < SPICE_N_ELEMENTS(atom2agent), FALSE); + + atom = gdk_atom_intern_static_string(atom2agent[m].xatom); + gtk_clipboard_request_contents(cb, atom, clipboard_received_cb, + weak_ref(G_OBJECT(self))); + + return TRUE; +} + +static void clipboard_release(SpiceMainChannel *main, guint selection, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + GtkClipboard* clipboard = get_clipboard_from_selection(s, selection); + + if (!clipboard) + return; + + s->nclip_targets[selection] = 0; + + if (!s->clipboard_by_guest[selection]) + return; + gtk_clipboard_clear(clipboard); + s->clipboard_by_guest[selection] = FALSE; +} + +static void channel_new(SpiceSession *session, SpiceChannel *channel, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + SPICE_DEBUG("Changing main channel from %p to %p", s->main, channel); + s->main = SPICE_MAIN_CHANNEL(channel); + g_signal_connect(channel, "main-clipboard-selection-grab", + G_CALLBACK(clipboard_grab), self); + g_signal_connect(channel, "main-clipboard-selection-request", + G_CALLBACK(clipboard_request), self); + g_signal_connect(channel, "main-clipboard-selection-release", + G_CALLBACK(clipboard_release), self); + } + if (SPICE_IS_INPUTS_CHANNEL(channel)) { + spice_g_signal_connect_object(channel, "inputs-modifiers", + G_CALLBACK(guest_modifiers_changed), self, 0); + spice_gtk_session_sync_keyboard_modifiers_for_channel(self, SPICE_INPUTS_CHANNEL(channel), TRUE); + } +} + +static void channel_destroy(SpiceSession *session, SpiceChannel *channel, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); + + SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + guint i; + + if (SPICE_IS_MAIN_CHANNEL(channel) && SPICE_MAIN_CHANNEL(channel) == s->main) { + s->main = NULL; + for (i = 0; i < CLIPBOARD_LAST; ++i) { + if (s->clipboard_by_guest[i]) { + GtkClipboard *cb = get_clipboard_from_selection(s, i); + if (cb) + gtk_clipboard_clear(cb); + s->clipboard_by_guest[i] = FALSE; + } + s->clip_grabbed[i] = FALSE; + s->nclip_targets[i] = 0; + } + } +} + +static gboolean read_only(SpiceGtkSession *self) +{ + return spice_session_get_read_only(self->priv->session); +} + +/* ---------------------------------------------------------------- */ +/* private functions (usbredir related) */ +G_GNUC_INTERNAL +void spice_gtk_session_request_auto_usbredir(SpiceGtkSession *self, + gboolean state) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + + SpiceGtkSessionPrivate *s = self->priv; + SpiceDesktopIntegration *desktop_int; + SpiceUsbDeviceManager *manager; + + if (state) { + s->auto_usbredir_reqs++; + if (s->auto_usbredir_reqs != 1) + return; + } else { + g_return_if_fail(s->auto_usbredir_reqs > 0); + s->auto_usbredir_reqs--; + if (s->auto_usbredir_reqs != 0) + return; + } + + if (!s->auto_usbredir_enable) + return; + + manager = spice_usb_device_manager_get(s->session, NULL); + if (!manager) + return; + + g_object_set(manager, "auto-connect", state, NULL); + + desktop_int = spice_desktop_integration_get(s->session); + if (state) + spice_desktop_integration_inhibit_automount(desktop_int); + else + spice_desktop_integration_uninhibit_automount(desktop_int); +} + +/* ------------------------------------------------------------------ */ +/* public functions */ + +/** + * spice_gtk_session_get: + * @session: #SpiceSession for which to get the #SpiceGtkSession + * + * Gets the #SpiceGtkSession associated with the passed in #SpiceSession. + * A new #SpiceGtkSession instance will be created the first time this + * function is called for a certain #SpiceSession. + * + * Note that this function returns a weak reference, which should not be used + * after the #SpiceSession itself has been unref-ed by the caller. + * + * Returns: (transfer none): a weak reference to the #SpiceGtkSession associated with the passed in #SpiceSession + * + * Since 0.8 + **/ +SpiceGtkSession *spice_gtk_session_get(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceGtkSession *self; + static GMutex mutex; + + g_mutex_lock(&mutex); + self = g_object_get_data(G_OBJECT(session), "spice-gtk-session"); + if (self == NULL) { + self = g_object_new(SPICE_TYPE_GTK_SESSION, "session", session, NULL); + g_object_set_data_full(G_OBJECT(session), "spice-gtk-session", self, g_object_unref); + } + g_mutex_unlock(&mutex); + + return SPICE_GTK_SESSION(self); +} + +/** + * spice_gtk_session_copy_to_guest: + * @self: #SpiceGtkSession + * + * Copy client-side clipboard to guest clipboard. + * + * Since 0.8 + **/ +void spice_gtk_session_copy_to_guest(SpiceGtkSession *self) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + g_return_if_fail(read_only(self) == FALSE); + + SpiceGtkSessionPrivate *s = self->priv; + int selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + + if (s->clip_hasdata[selection] && !s->clip_grabbed[selection]) { + gtk_clipboard_request_targets(s->clipboard, clipboard_get_targets, + weak_ref(G_OBJECT(self))); + } +} + +/** + * spice_gtk_session_paste_from_guest: + * @self: #SpiceGtkSession + * + * Copy guest clipboard to client-side clipboard. + * + * Since 0.8 + **/ +void spice_gtk_session_paste_from_guest(SpiceGtkSession *self) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + g_return_if_fail(read_only(self) == FALSE); + + SpiceGtkSessionPrivate *s = self->priv; + int selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + + if (s->nclip_targets[selection] == 0) { + g_warning("Guest clipboard is not available."); + return; + } + + if (!gtk_clipboard_set_with_owner(s->clipboard, s->clip_targets[selection], s->nclip_targets[selection], + clipboard_get, clipboard_clear, G_OBJECT(self))) { + g_warning("Clipboard grab failed"); + return; + } + s->clipboard_by_guest[selection] = TRUE; + s->clip_hasdata[selection] = FALSE; +} + +G_GNUC_INTERNAL +void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self) +{ + GList *l = NULL, *channels = spice_session_get_channels(self->priv->session); + + for (l = channels; l != NULL; l = l->next) { + if (SPICE_IS_INPUTS_CHANNEL(l->data)) { + SpiceInputsChannel *inputs = SPICE_INPUTS_CHANNEL(l->data); + spice_gtk_session_sync_keyboard_modifiers_for_channel(self, inputs, TRUE); + } + } + g_list_free(channels); +} + +G_GNUC_INTERNAL +void spice_gtk_session_set_pointer_grabbed(SpiceGtkSession *self, gboolean grabbed) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + + self->priv->pointer_grabbed = grabbed; + g_object_notify(G_OBJECT(self), "pointer-grabbed"); +} + +G_GNUC_INTERNAL +gboolean spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self) +{ + g_return_val_if_fail(SPICE_IS_GTK_SESSION(self), FALSE); + + return self->priv->pointer_grabbed; +} + +G_GNUC_INTERNAL +void spice_gtk_session_set_keyboard_has_focus(SpiceGtkSession *self, + gboolean keyboard_has_focus) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + + self->priv->keyboard_has_focus = keyboard_has_focus; +} + +G_GNUC_INTERNAL +void spice_gtk_session_set_mouse_has_pointer(SpiceGtkSession *self, + gboolean mouse_has_pointer) +{ + g_return_if_fail(SPICE_IS_GTK_SESSION(self)); + self->priv->mouse_has_pointer = mouse_has_pointer; +} + +G_GNUC_INTERNAL +gboolean spice_gtk_session_get_keyboard_has_focus(SpiceGtkSession *self) +{ + g_return_val_if_fail(SPICE_IS_GTK_SESSION(self), FALSE); + + return self->priv->keyboard_has_focus; +} + +G_GNUC_INTERNAL +gboolean spice_gtk_session_get_mouse_has_pointer(SpiceGtkSession *self) +{ + g_return_val_if_fail(SPICE_IS_GTK_SESSION(self), FALSE); + + return self->priv->mouse_has_pointer; +} diff --git a/src/spice-gtk-session.h b/src/spice-gtk-session.h new file mode 100644 index 0000000..b04f4fc --- /dev/null +++ b/src/spice-gtk-session.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_GTK_SESSION_H__ +#define __SPICE_CLIENT_GTK_SESSION_H__ + +#if !defined(__SPICE_CLIENT_GTK_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_GTK_SESSION (spice_gtk_session_get_type ()) +#define SPICE_GTK_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_GTK_SESSION, SpiceGtkSession)) +#define SPICE_GTK_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_GTK_SESSION, SpiceGtkSessionClass)) +#define SPICE_IS_GTK_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_GTK_SESSION)) +#define SPICE_IS_GTK_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_GTK_SESSION)) +#define SPICE_GTK_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_GTK_SESSION, SpiceGtkSessionClass)) + +typedef struct _SpiceGtkSession SpiceGtkSession; +typedef struct _SpiceGtkSessionClass SpiceGtkSessionClass; + +GType spice_gtk_session_get_type(void); + +SpiceGtkSession *spice_gtk_session_get(SpiceSession *session); +void spice_gtk_session_copy_to_guest(SpiceGtkSession *self); +void spice_gtk_session_paste_from_guest(SpiceGtkSession *self); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_GTK_SESSION_H__ */ diff --git a/src/spice-gtk-sym-file b/src/spice-gtk-sym-file new file mode 100644 index 0000000..e52334b --- /dev/null +++ b/src/spice-gtk-sym-file @@ -0,0 +1,21 @@ +spice_display_get_grab_keys +spice_display_get_pixbuf +spice_display_get_type +spice_display_key_event_get_type +spice_display_mouse_ungrab +spice_display_new +spice_display_new_with_monitor +spice_display_send_keys +spice_display_set_grab_keys +spice_grab_sequence_as_string +spice_grab_sequence_copy +spice_grab_sequence_free +spice_grab_sequence_get_type +spice_grab_sequence_new +spice_grab_sequence_new_from_string +spice_gtk_session_copy_to_guest +spice_gtk_session_get +spice_gtk_session_get_type +spice_gtk_session_paste_from_guest +spice_usb_device_widget_get_type +spice_usb_device_widget_new diff --git a/src/spice-marshal.txt b/src/spice-marshal.txt new file mode 100644 index 0000000..86673bd --- /dev/null +++ b/src/spice-marshal.txt @@ -0,0 +1,15 @@ +VOID:INT,INT +VOID:INT,INT,INT +VOID:INT,INT,INT,INT +VOID:UINT,UINT,UINT,UINT +VOID:INT,INT,INT,INT,POINTER +VOID:INT,INT,INT,INT,INT,POINTER +VOID:POINTER,INT +BOOLEAN:POINTER,UINT +BOOLEAN:UINT +VOID:UINT,POINTER,UINT +VOID:UINT,UINT,POINTER,UINT +BOOLEAN:UINT,POINTER,UINT +BOOLEAN:UINT,UINT +VOID:OBJECT,OBJECT +VOID:BOXED,BOXED diff --git a/src/spice-option.c b/src/spice-option.c new file mode 100644 index 0000000..4d5aab2 --- /dev/null +++ b/src/spice-option.c @@ -0,0 +1,323 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#include +#include "spice-session.h" +#include "spice-util.h" +#include "spice-channel-priv.h" +#include "usb-device-manager.h" + +static GStrv disable_effects = NULL; +static gint color_depth = 0; +static char *ca_file = NULL; +static char *host_subject = NULL; +static char *smartcard_db = NULL; +static char *smartcard_certificates = NULL; +static char *usbredir_auto_redirect_filter = NULL; +static char *usbredir_redirect_on_connect = NULL; +static gboolean smartcard = FALSE; +static gboolean disable_audio = FALSE; +static gboolean disable_usbredir = FALSE; +static gint cache_size = 0; +static gint glz_window_size = 0; +static gchar *secure_channels = NULL; +static gchar *shared_dir = NULL; +static SpiceImageCompression preferred_compression = SPICE_IMAGE_COMPRESSION_INVALID; + +G_GNUC_NORETURN +static void option_version(void) +{ + g_print(PACKAGE_STRING "\n"); + exit(0); +} + +static gboolean option_debug(void) +{ + spice_util_set_debug(TRUE); + return TRUE; +} + +static gboolean parse_color_depth(const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + unsigned long parsed_depth; + char *end; + + if (option_name == NULL) { + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("missing color depth, must be 16 or 32")); + return FALSE; + } + + parsed_depth = strtoul(value, &end, 0); + if (*end != '\0') + goto error; + + if ((parsed_depth != 16) && (parsed_depth != 32)) + goto error; + + color_depth = parsed_depth; + + return TRUE; + +error: + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("invalid color depth (%s), must be 16 or 32"), value); + return FALSE; +} + +static gboolean parse_disable_effects(const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + GStrv it; + + disable_effects = g_strsplit(value, ",", -1); + for (it = disable_effects; *it != NULL; it++) { + if ((g_strcmp0(*it, "wallpaper") != 0) + && (g_strcmp0(*it, "font-smooth") != 0) + && (g_strcmp0(*it, "animation") != 0) + && (g_strcmp0(*it, "all") != 0)) { + /* Translators: do not translate 'wallpaper', 'font-smooth', + * 'animation', 'all' as the user must use these values with the + * --spice-disable-effects command line option + */ + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, + _("invalid effect name (%s), must be 'wallpaper', 'font-smooth', 'animation' or 'all'"), *it); + g_clear_pointer(&disable_effects, g_strfreev); + return FALSE; + } + } + + return TRUE; +} + +static gboolean parse_secure_channels(const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + gint i; + gchar **channels = g_strsplit(value, ",", -1); + + g_return_val_if_fail(channels != NULL, FALSE); + + for (i = 0; channels[i]; i++) { + if (g_strcmp0(channels[i], "all") == 0) + continue; + + if (spice_channel_string_to_type(channels[i]) == -1) { + gchar *supported = spice_channel_supported_string(); + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, + _("invalid channel name (%s), valid names: all, %s"), + channels[i], supported); + g_free(supported); + return FALSE; + } + } + + g_strfreev(channels); + + secure_channels = g_strdup(value); + + return TRUE; +} + + +static gboolean parse_usbredir_filter(const gchar *option_name, + const gchar *value, + gpointer data, GError **error) + +{ + g_warning("--spice-usbredir-filter is deprecated, please use --spice-usbredir-auto-redirect-filter instead"); + g_free(usbredir_auto_redirect_filter); + usbredir_auto_redirect_filter = g_strdup(value); + return TRUE; +} + +static gboolean parse_preferred_compression(const gchar *option_name, const gchar *value, + gpointer data, GError **error) +{ + if (!strcmp(value, "auto-glz")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_AUTO_GLZ; + } else if (!strcmp(value, "auto-lz")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_AUTO_LZ; + } else if (!strcmp(value, "quic")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_QUIC; + } else if (!strcmp(value, "glz")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_GLZ; + } else if (!strcmp(value, "lz")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_LZ; +#ifdef USE_LZ4 + } else if (!strcmp(value, "lz4")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_LZ4; +#endif + } else if (!strcmp(value, "off")) { + preferred_compression = SPICE_IMAGE_COMPRESSION_OFF; + } else { + preferred_compression = SPICE_IMAGE_COMPRESSION_INVALID; + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, + _("Image compression algorithm %s not supported"), value); + return FALSE; + } + return TRUE; +} + +/** + * spice_get_option_group: + * + * Gets commandline options. + * + * Bindings for other languages are available since 0.32 + * + * Returns: (transfer full): a #GOptionGroup for the commandline + * arguments specific to Spice. You have to call + * spice_set_session_option() after to set the options on a + * #SpiceSession. + **/ +GOptionGroup* spice_get_option_group(void) +{ + const GOptionEntry entries[] = { + { "spice-secure-channels", '\0', 0, G_OPTION_ARG_CALLBACK, parse_secure_channels, + N_("Force the specified channels to be secured"), "" }, + { "spice-disable-effects", '\0', 0, G_OPTION_ARG_CALLBACK, parse_disable_effects, + N_("Disable guest display effects"), "" }, + { "spice-color-depth", '\0', 0, G_OPTION_ARG_CALLBACK, parse_color_depth, + N_("Guest display color depth"), "<16,32>" }, + { "spice-ca-file", '\0', 0, G_OPTION_ARG_FILENAME, &ca_file, + N_("Truststore file for secure connections"), N_("") }, + { "spice-host-subject", '\0', 0, G_OPTION_ARG_STRING, &host_subject, + N_("Subject of the host certificate (field=value pairs separated by commas)"), N_("") }, + { "spice-disable-audio", '\0', 0, G_OPTION_ARG_NONE, &disable_audio, + N_("Disable audio support"), NULL }, + { "spice-smartcard", '\0', 0, G_OPTION_ARG_NONE, &smartcard, + N_("Enable smartcard support"), NULL }, + { "spice-smartcard-certificates", '\0', 0, G_OPTION_ARG_STRING, &smartcard_certificates, + N_("Certificates to use for software smartcards (field=values separated by commas)"), N_("") }, + { "spice-smartcard-db", '\0', 0, G_OPTION_ARG_STRING, &smartcard_db, + N_("Path to the local certificate database to use for software smartcard certificates"), N_("") }, + { "spice-disable-usbredir", '\0', 0, G_OPTION_ARG_NONE, &disable_usbredir, + N_("Disable USB redirection support"), NULL }, + /* Backward compats version of spice-usbredir-auto-redirect-filter */ + { "spice-usbredir-filter", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, parse_usbredir_filter, + NULL, NULL }, + { "spice-usbredir-auto-redirect-filter", '\0', 0, G_OPTION_ARG_STRING, &usbredir_auto_redirect_filter, + N_("Filter selecting USB devices to be auto-redirected when plugged in"), N_("") }, + { "spice-usbredir-redirect-on-connect", '\0', 0, G_OPTION_ARG_STRING, &usbredir_redirect_on_connect, + N_("Filter selecting USB devices to redirect on connect"), N_("") }, + { "spice-cache-size", '\0', 0, G_OPTION_ARG_INT, &cache_size, + N_("Image cache size"), N_("") }, + { "spice-glz-window-size", '\0', 0, G_OPTION_ARG_INT, &glz_window_size, + N_("Glz compression history size"), N_("") }, + { "spice-shared-dir", '\0', 0, G_OPTION_ARG_FILENAME, &shared_dir, + N_("Shared directory"), N_("") }, + { "spice-preferred-compression", '\0', 0, G_OPTION_ARG_CALLBACK, parse_preferred_compression, + N_("Preferred image compression algorithm"), +#ifdef USE_LZ4 + "" }, +#else + "" }, +#endif + + { "spice-debug", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_debug, + N_("Enable Spice-GTK debugging"), NULL }, + { "spice-gtk-version", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_version, + N_("Display Spice-GTK version information"), NULL }, + { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + }; + GOptionGroup *grp; + + grp = g_option_group_new("spice", _("Spice Options:"), _("Show Spice Options"), NULL, NULL); + g_option_group_add_entries(grp, entries); + + return grp; +} + +/** + * spice_set_session_option: + * @session: a #SpiceSession to set option upon + * + * Set various properties on @session, according to the commandline + * arguments given to spice_get_option_group() option group. + **/ +void spice_set_session_option(SpiceSession *session) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + if (ca_file == NULL) { + const char *homedir = g_getenv("HOME"); + if (!homedir) + homedir = g_get_home_dir(); + ca_file = g_build_filename(homedir, ".spicec", "spice_truststore.pem", NULL); + if (!g_file_test(ca_file, G_FILE_TEST_IS_REGULAR)) + g_clear_pointer(&ca_file, g_free); + } + + if (disable_effects) { + g_object_set(session, "disable-effects", disable_effects, NULL); + } + + if (secure_channels) { + GStrv channels; + channels = g_strsplit(secure_channels, ",", -1); + if (channels) + g_object_set(session, "secure-channels", channels, NULL); + g_strfreev(channels); + } + + if (color_depth) + g_object_set(session, "color-depth", color_depth, NULL); + if (ca_file) + g_object_set(session, "ca-file", ca_file, NULL); + if (host_subject) + g_object_set(session, "cert-subject", host_subject, NULL); + if (smartcard) { + g_object_set(session, "enable-smartcard", smartcard, NULL); + if (smartcard_certificates) { + GStrv certs_strv; + certs_strv = g_strsplit(smartcard_certificates, ",", -1); + if (certs_strv) + g_object_set(session, "smartcard-certificates", certs_strv, NULL); + g_strfreev(certs_strv); + } + if (smartcard_db) + g_object_set(session, "smartcard-db", smartcard_db, NULL); + } + if (usbredir_auto_redirect_filter) { + SpiceUsbDeviceManager *m = spice_usb_device_manager_get(session, NULL); + if (m) + g_object_set(m, "auto-connect-filter", + usbredir_auto_redirect_filter, NULL); + } + if (usbredir_redirect_on_connect) { + SpiceUsbDeviceManager *m = spice_usb_device_manager_get(session, NULL); + if (m) + g_object_set(m, "redirect-on-connect", + usbredir_redirect_on_connect, NULL); + } + if (disable_usbredir) + g_object_set(session, "enable-usbredir", FALSE, NULL); + if (disable_audio) + g_object_set(session, "enable-audio", FALSE, NULL); + if (cache_size) + g_object_set(session, "cache-size", cache_size, NULL); + if (glz_window_size) + g_object_set(session, "glz-window-size", glz_window_size, NULL); + if (shared_dir) + g_object_set(session, "shared-dir", shared_dir, NULL); + if (preferred_compression != SPICE_IMAGE_COMPRESSION_INVALID) + g_object_set(session, "preferred-compression", preferred_compression, NULL); +} diff --git a/src/spice-option.h b/src/spice-option.h new file mode 100644 index 0000000..847e14c --- /dev/null +++ b/src/spice-option.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICE_OPTION_H +#define SPICE_OPTION_H + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include "spice-session.h" + +G_BEGIN_DECLS + +GOptionGroup* spice_get_option_group(void); +void spice_set_session_option(SpiceSession *session); + +G_END_DECLS + +#endif /* SPICE_OPTION_H */ diff --git a/src/spice-pulse.c b/src/spice-pulse.c new file mode 100644 index 0000000..5248bc3 --- /dev/null +++ b/src/spice-pulse.c @@ -0,0 +1,1307 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-pulse.h" +#include "spice-common.h" +#include "spice-session-priv.h" +#include "spice-channel-priv.h" +#include "spice-util-priv.h" + +#include +#include +#include + +#define SPICE_PULSE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE, SpicePulsePrivate)) + +struct async_task { + SpicePulse *pulse; + SpiceMainChannel *main_channel; + GTask *gtask; + GAsyncReadyCallback callback; + gpointer user_data; + gboolean is_playback; + pa_operation *pa_op; + gulong cancel_id; +}; + +struct stream { + pa_sample_spec spec; + pa_stream *stream; + int state; + pa_operation *uncork_op; + pa_operation *cork_op; + gboolean started; + guint num_underflow; + gboolean info_updated; + gchar *name; + pa_ext_stream_restore_info info; +}; + +struct _SpicePulsePrivate { + SpiceChannel *pchannel; + SpiceChannel *rchannel; + + pa_glib_mainloop *mainloop; + pa_context *context; + int state; + struct stream playback; + struct stream record; + guint last_delay; + guint target_delay; + struct async_task *pending_restore_task; + GList *results; +}; + +G_DEFINE_TYPE(SpicePulse, spice_pulse, SPICE_TYPE_AUDIO) + +static const char *stream_state_names[] = { + [ PA_STREAM_UNCONNECTED ] = "unconnected", + [ PA_STREAM_CREATING ] = "creating", + [ PA_STREAM_READY ] = "ready", + [ PA_STREAM_FAILED ] = "failed", + [ PA_STREAM_TERMINATED ] = "terminated", +}; + +static const char *context_state_names[] = { + [ PA_CONTEXT_UNCONNECTED ] = "unconnected", + [ PA_CONTEXT_CONNECTING ] = "connecting", + [ PA_CONTEXT_AUTHORIZING ] = "authorizing", + [ PA_CONTEXT_SETTING_NAME ] = "setting_name", + [ PA_CONTEXT_READY ] = "ready", + [ PA_CONTEXT_FAILED ] = "failed", + [ PA_CONTEXT_TERMINATED ] = "terminated", +}; +#define STATE_NAME(array, state) \ + ((state < G_N_ELEMENTS(array)) ? array[state] : NULL) + +static void stream_stop(SpicePulse *pulse, struct stream *s); +static gboolean connect_channel(SpiceAudio *audio, SpiceChannel *channel); +static void channel_weak_notified(gpointer data, GObject *where_the_object_was); +static void spice_pulse_get_playback_volume_info_async(SpiceAudio *audio, GCancellable *cancellable, + SpiceMainChannel *main_channel, GAsyncReadyCallback callback, gpointer user_data); +static gboolean spice_pulse_get_playback_volume_info_finish(SpiceAudio *audio, GAsyncResult *res, + gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); +static void spice_pulse_get_record_volume_info_async(SpiceAudio *audio, GCancellable *cancellable, + SpiceMainChannel *main_channel, GAsyncReadyCallback callback, gpointer user_data); +static gboolean spice_pulse_get_record_volume_info_finish(SpiceAudio *audio,GAsyncResult *res, + gboolean *mute, guint8 *nchannels, guint16 **volume, GError **error); +static void stream_restore_read_cb(pa_context *context, + const pa_ext_stream_restore_info *info, int eol, void *userdata); +static void spice_pulse_complete_async_task(struct async_task *task, const gchar *err_msg); +static void spice_pulse_complete_all_async_tasks(SpicePulse *pulse, const gchar *err_msg); + +static void spice_pulse_finalize(GObject *obj) +{ + SpicePulse *pulse = SPICE_PULSE(obj); + SpicePulsePrivate *p; + + p = pulse->priv; + + if (p->context != NULL) + pa_context_unref(p->context); + + if (p->mainloop != NULL) + pa_glib_mainloop_free(p->mainloop); + + G_OBJECT_CLASS(spice_pulse_parent_class)->finalize(obj); +} + +static void spice_pulse_dispose(GObject *obj) +{ + SpicePulse *pulse = SPICE_PULSE(obj); + SpicePulsePrivate *p; + + SPICE_DEBUG("%s", __FUNCTION__); + p = pulse->priv; + + g_clear_pointer(&p->playback.uncork_op, pa_operation_unref); + g_clear_pointer(&p->playback.cork_op, pa_operation_unref); + g_clear_pointer(&p->record.uncork_op, pa_operation_unref); + g_clear_pointer(&p->record.cork_op, pa_operation_unref); + + if (p->results != NULL) + spice_pulse_complete_all_async_tasks(pulse, "PulseAudio is being dispose"); + + g_clear_pointer(&p->playback.name, g_free); + g_clear_pointer(&p->record.name, g_free); + + if (p->pchannel) + g_object_weak_unref(G_OBJECT(p->pchannel), channel_weak_notified, pulse); + p->pchannel = NULL; + + if (p->rchannel) + g_object_weak_unref(G_OBJECT(p->rchannel), channel_weak_notified, pulse); + p->rchannel = NULL; + + G_OBJECT_CLASS(spice_pulse_parent_class)->dispose(obj); +} + +static void spice_pulse_init(SpicePulse *pulse) +{ + pulse->priv = SPICE_PULSE_GET_PRIVATE(pulse); +} + +static void spice_pulse_class_init(SpicePulseClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + SpiceAudioClass *audio_class = SPICE_AUDIO_CLASS(klass); + + audio_class->connect_channel = connect_channel; + audio_class->get_playback_volume_info_async = spice_pulse_get_playback_volume_info_async; + audio_class->get_playback_volume_info_finish = spice_pulse_get_playback_volume_info_finish; + audio_class->get_record_volume_info_async = spice_pulse_get_record_volume_info_async; + audio_class->get_record_volume_info_finish = spice_pulse_get_record_volume_info_finish; + + gobject_class->finalize = spice_pulse_finalize; + gobject_class->dispose = spice_pulse_dispose; + + g_type_class_add_private(klass, sizeof(SpicePulsePrivate)); +} + +/* ------------------------------------------------------------------ */ +static void pulse_uncork_cb(pa_stream *pastream, int success, void *data) +{ + struct stream *s = data; + + if (!success) + g_warning("pulseaudio uncork operation failed"); + + g_clear_pointer(&s->uncork_op, pa_operation_unref); +} + +static void stream_uncork(SpicePulse *pulse, struct stream *s) +{ + SpicePulsePrivate *p = pulse->priv; + pa_operation *o = NULL; + + g_return_if_fail(s->stream); + + if (s->cork_op) { + pa_operation_cancel(s->cork_op); + g_clear_pointer(&s->cork_op, pa_operation_unref); + } + + if (pa_stream_is_corked(s->stream) && !s->uncork_op) { + if (!(o = pa_stream_cork(s->stream, 0, pulse_uncork_cb, s))) { + g_warning("pa_stream_uncork() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } + s->uncork_op = o; + } +} + +static void pulse_flush_cb(pa_stream *pastream, int success, void *data) +{ + struct stream *s = data; + + if (!success) + g_warning("pulseaudio flush operation failed"); + + g_clear_pointer(&s->cork_op, pa_operation_unref); +} + +static void pulse_cork_flush_cb(pa_stream *pastream, int success, void *data) +{ + struct stream *s = data; + + if (!success) + g_warning("pulseaudio cork operation failed"); + + pa_operation_unref(s->cork_op); + + if (!(s->cork_op = pa_stream_flush(s->stream, pulse_flush_cb, s))) { + g_warning("pa_stream_flush() failed"); + } +} + +static void pulse_cork_cb(pa_stream *pastream, int success, void *data) +{ + struct stream *s = data; + + SPICE_DEBUG("%s: cork started", __FUNCTION__); + if (!success) + g_warning("pulseaudio cork operation failed"); + + g_clear_pointer(&s->cork_op, pa_operation_unref); +} + +static void stream_cork(SpicePulse *pulse, struct stream *s, gboolean with_flush) +{ + SpicePulsePrivate *p = pulse->priv; + pa_operation *o = NULL; + + if (s->uncork_op) { + pa_operation_cancel(s->uncork_op); + g_clear_pointer(&s->uncork_op, pa_operation_unref); + } + + if (!pa_stream_is_corked(s->stream) && !s->cork_op) { + if (!(o = pa_stream_cork(s->stream, 1, + with_flush ? pulse_cork_flush_cb : + pulse_cork_cb, + s))) { + g_warning("pa_stream_cork() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } + s->cork_op = o; + } +} + +static void stream_stop(SpicePulse *pulse, struct stream *s) +{ + SpicePulsePrivate *p = pulse->priv; + + if (pa_stream_disconnect(s->stream) < 0) { + g_warning("pa_stream_disconnect() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } + g_clear_pointer(&s->stream, pa_stream_unref); +} + +static void stream_state_callback(pa_stream *s, void *userdata) +{ + SpicePulse *pulse = userdata; + SpicePulsePrivate *p; + + p = pulse->priv; + + g_return_if_fail(p != NULL); + g_return_if_fail(s != NULL); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: + case PA_STREAM_READY: + break; + case PA_STREAM_FAILED: + default: + g_warning("Stream error: %s", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + } +} + +static void stream_underflow_cb(pa_stream *s, void *userdata) +{ + SpicePulse *pulse = userdata; + SpicePulsePrivate *p; + + SPICE_DEBUG("PA stream underflow!!"); + + p = pulse->priv; + g_return_if_fail(p != NULL); + p->playback.num_underflow++; +#ifdef PULSE_ADJUST_LATENCY + const pa_buffer_attr *buffer_attr; + pa_buffer_attr new_buffer_attr; + pa_operation *op; + + buffer_attr = pa_stream_get_buffer_attr(s); + g_return_if_fail(buffer_attr != NULL); + + new_buffer_attr = *buffer_attr; + new_buffer_attr.tlength *= 2; + new_buffer_attr.minreq *= 2; + op = pa_stream_set_buffer_attr(s, &new_buffer_attr, NULL, NULL); + pa_operation_unref(op); +#endif +} + +static void stream_update_latency_callback(pa_stream *s, void *userdata) +{ + SpicePulse *pulse = userdata; + pa_usec_t usec; + int negative = 0; + SpicePulsePrivate *p; + + p = pulse->priv; + + g_return_if_fail(s != NULL); + g_return_if_fail(p != NULL); + + if (!p->playback.stream || !p->playback.started) + return; + + if (pa_stream_get_latency(s, &usec, &negative) < 0) { + g_warning("Failed to get latency: %s", pa_strerror(pa_context_errno(p->context))); + return; + } + + g_return_if_fail(negative == FALSE); + p->last_delay = usec / PA_USEC_PER_MSEC; + spice_playback_channel_set_delay(SPICE_PLAYBACK_CHANNEL(p->pchannel), usec / 1000); + if (pa_stream_is_corked(p->playback.stream)) { + if (p->last_delay >= p->target_delay) { + SPICE_DEBUG("%s: uncork playback. delay %u target %u", __FUNCTION__, p->last_delay, p->target_delay); + stream_uncork(pulse, &p->playback); + } else { + SPICE_DEBUG("%s: still corked. delay %u target %u", __FUNCTION__, p->last_delay, p->target_delay); + } + } +} + +static void create_playback(SpicePulse *pulse) +{ + SpicePulsePrivate *p = pulse->priv; + pa_stream_flags_t flags; + pa_buffer_attr buffer_attr = { 0, }; + + g_return_if_fail(p != NULL); + g_return_if_fail(p->context != NULL); + g_return_if_fail(p->playback.stream == NULL); + g_return_if_fail(pa_context_get_state(p->context) == PA_CONTEXT_READY); + + p->playback.state = PA_STREAM_READY; + p->playback.stream = pa_stream_new(p->context, "playback", + &p->playback.spec, NULL); + pa_stream_set_state_callback(p->playback.stream, stream_state_callback, pulse); + pa_stream_set_underflow_callback(p->playback.stream, stream_underflow_cb, pulse); + pa_stream_set_latency_update_callback(p->playback.stream, stream_update_latency_callback, pulse); + + buffer_attr.maxlength = -1; + buffer_attr.tlength = pa_usec_to_bytes(p->target_delay * PA_USEC_PER_MSEC, &p->playback.spec); + buffer_attr.prebuf = -1; + buffer_attr.minreq = -1; + flags = PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE; + + if (pa_stream_connect_playback(p->playback.stream, + NULL, &buffer_attr, flags, NULL, NULL) < 0) { + g_warning("pa_stream_connect_playback() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } +} + +static void playback_start(SpicePlaybackChannel *channel, gint format, gint channels, + gint frequency, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + pa_context_state_t state; + guint latency; + + g_return_if_fail(p != NULL); + + p->playback.started = TRUE; + p->playback.num_underflow = 0; + g_object_get(p->pchannel, "min-latency", &latency, NULL); + + if (p->playback.stream && + (p->playback.spec.rate != frequency || + p->playback.spec.channels != channels || + p->target_delay != latency)) { + stream_stop(pulse, &p->playback); + } + + g_return_if_fail(format == SPICE_AUDIO_FMT_S16); + p->playback.spec.format = PA_SAMPLE_S16LE; + p->playback.spec.rate = frequency; + p->playback.spec.channels = channels; + p->target_delay = latency; + p->last_delay = 0; + + state = pa_context_get_state(p->context); + switch (state) { + case PA_CONTEXT_READY: + if (p->state != state) { + SPICE_DEBUG("%s: pulse context ready", __FUNCTION__); + } + if (p->playback.stream == NULL) { + create_playback(pulse); + } else + stream_uncork(pulse, &p->playback); + break; + default: + if (p->state != state) { + SPICE_DEBUG("%s: pulse context not ready (%s)", + __FUNCTION__, STATE_NAME(context_state_names, state)); + } + break; + } + p->state = state; +} + +static void playback_data(SpicePlaybackChannel *channel, + gpointer *audio, gint size, + gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + pa_stream_state_t state; + + if (!p->playback.stream) + return; + + state = pa_stream_get_state(p->playback.stream); + switch (state) { + case PA_STREAM_CREATING: + SPICE_DEBUG("stream creating, dropping data"); + break; + case PA_STREAM_READY: + if (p->playback.state != state) { + SPICE_DEBUG("%s: pulse playback stream ready", __FUNCTION__); + } + if (pa_stream_write(p->playback.stream, audio, size, NULL, 0, PA_SEEK_RELATIVE) < 0) { + g_warning("pa_stream_write() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } + break; + default: + if (p->playback.state != state) { + SPICE_DEBUG("%s: pulse playback stream not ready (%s)", + __FUNCTION__, STATE_NAME(stream_state_names, state)); + } + break; + } + p->playback.state = state; +} + +static void playback_stop(SpicePulse *pulse) +{ + SpicePulsePrivate *p = pulse->priv; + + SPICE_DEBUG("%s: #underflow %u", __FUNCTION__, p->playback.num_underflow); + + p->playback.started = FALSE; + if (!p->playback.stream) + return; + + stream_cork(pulse, &p->playback, TRUE); +} + +static void stream_read_callback(pa_stream *s, size_t length, void *data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + + g_return_if_fail(p != NULL); + + while (pa_stream_readable_size(s) > 0) { + const void *snddata; + + if (pa_stream_peek(s, &snddata, &length) < 0) { + g_warning("pa_stream_peek() failed: %s", + pa_strerror(pa_context_errno(p->context))); + return; + } + + g_return_if_fail(snddata); + g_return_if_fail(length > 0); + + if (p->rchannel != NULL) + spice_record_send_data(SPICE_RECORD_CHANNEL(p->rchannel), + /* FIXME: server side doesn't care about ts? + what is the unit? ms apparently */ + (gpointer)snddata, length, 0); + + if (pa_stream_drop(s) < 0) { + g_warning("pa_stream_drop() failed: %s", + pa_strerror(pa_context_errno(p->context))); + return; + } + } +} + +static void create_record(SpicePulse *pulse) +{ + SpicePulsePrivate *p = pulse->priv; + pa_buffer_attr buffer_attr = { 0, }; + pa_stream_flags_t flags; + + g_return_if_fail(p != NULL); + g_return_if_fail(p->context != NULL); + g_return_if_fail(p->record.stream == NULL); + g_return_if_fail(pa_context_get_state(p->context) == PA_CONTEXT_READY); + + p->record.state = PA_STREAM_READY; + p->record.stream = pa_stream_new(p->context, "record", + &p->record.spec, NULL); + pa_stream_set_read_callback(p->record.stream, stream_read_callback, pulse); + pa_stream_set_state_callback(p->record.stream, stream_state_callback, pulse); + + /* FIXME: we might want customizable latency */ + buffer_attr.maxlength = -1; + buffer_attr.prebuf = -1; + buffer_attr.fragsize = buffer_attr.tlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC, &p->record.spec); + buffer_attr.minreq = (uint32_t) -1; + flags = PA_STREAM_ADJUST_LATENCY; + + if (pa_stream_connect_record(p->record.stream, NULL, &buffer_attr, flags) < 0) { + g_warning("pa_stream_connect_record() failed: %s", + pa_strerror(pa_context_errno(p->context))); + } +} + +static void record_start(SpiceRecordChannel *channel, gint format, gint channels, + gint frequency, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + pa_context_state_t state; + + p->record.started = TRUE; + + if (p->record.stream && + (p->record.spec.rate != frequency || + p->record.spec.channels != channels)) { + stream_stop(pulse, &p->record); + } + + g_return_if_fail(format == SPICE_AUDIO_FMT_S16); + p->record.spec.format = PA_SAMPLE_S16LE; + p->record.spec.rate = frequency; + p->record.spec.channels = channels; + + state = pa_context_get_state(p->context); + switch (state) { + case PA_CONTEXT_READY: + if (p->state != state) { + SPICE_DEBUG("%s: pulse context ready", __FUNCTION__); + } + if (p->record.stream == NULL) { + create_record(pulse); + } else + stream_uncork(pulse, &p->record); + break; + default: + if (p->state != state) { + g_warning("%s: pulse context not ready (%s)", + __FUNCTION__, STATE_NAME(context_state_names, state)); + } + break; + } + p->state = state; +} + +static void record_stop(SpicePulse *pulse) +{ + SpicePulsePrivate *p = pulse->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + p->record.started = FALSE; + if (!p->record.stream) + return; + + stream_stop(pulse, &p->record); +} + +static void playback_volume_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + guint16 *volume; + guint nchannels; + pa_operation *op; + pa_cvolume v; + guint i; + + g_object_get(object, + "volume", &volume, + "nchannels", &nchannels, + NULL); + + pa_cvolume_init(&v); + v.channels = p->playback.spec.channels; + for (i = 0; i < nchannels; ++i) { + v.values[i] = (PA_VOLUME_NORM - PA_VOLUME_MUTED) * volume[i] / G_MAXUINT16; + SPICE_DEBUG("playback volume changed %u", v.values[i]); + } + + if (!p->playback.stream || + pa_stream_get_index(p->playback.stream) == PA_INVALID_INDEX) + return; + + op = pa_context_set_sink_input_volume(p->context, + pa_stream_get_index(p->playback.stream), + &v, NULL, NULL); + if (!op) + g_warning("set_sink_input_volume() failed: %s", + pa_strerror(pa_context_errno(p->context))); + else + pa_operation_unref(op); +} + +static void playback_mute_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + gboolean mute; + pa_operation *op; + + g_object_get(object, "mute", &mute, NULL); + SPICE_DEBUG("playback mute changed %d", mute); + + if (!p->playback.stream || + pa_stream_get_index(p->playback.stream) == PA_INVALID_INDEX) + return; + + op = pa_context_set_sink_input_mute(p->context, + pa_stream_get_index(p->playback.stream), + mute, NULL, NULL); + if (!op) + g_warning("set_sink_input_mute() failed: %s", + pa_strerror(pa_context_errno(p->context))); + else + pa_operation_unref(op); +} + +static void playback_min_latency_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + guint min_latency; + + g_object_get(object, "min-latency", &min_latency, NULL); + p->target_delay = min_latency; + + if (p->last_delay < p->target_delay) { + SPICE_DEBUG("%s: corking", __FUNCTION__); + if (p->playback.stream) + stream_cork(pulse, &p->playback, FALSE); + } else { + SPICE_DEBUG("%s: not corking. The current delay satisfies the requirement", __FUNCTION__); + } +} + +static void record_mute_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + gboolean mute; + pa_operation *op; + + g_object_get(object, "mute", &mute, NULL); + SPICE_DEBUG("record mute changed %d", mute); + + if (!p->record.stream || + pa_stream_get_device_index(p->record.stream) == PA_INVALID_INDEX) + return; + +#if PA_CHECK_VERSION(1,0,0) + op = pa_context_set_source_output_mute(p->context, + pa_stream_get_index(p->record.stream), +#else + op = pa_context_set_source_mute_by_index(p->context, + pa_stream_get_device_index(p->record.stream), +#endif + mute, NULL, NULL); + if (!op) + g_warning("set_source_output_mute() failed: %s", + pa_strerror(pa_context_errno(p->context))); + else + pa_operation_unref(op); +} + +static void record_volume_changed(GObject *object, GParamSpec *pspec, gpointer data) +{ + SpicePulse *pulse = data; + SpicePulsePrivate *p = pulse->priv; + guint16 *volume; + guint nchannels; + pa_operation *op; + pa_cvolume v; + guint i; + + g_object_get(object, + "volume", &volume, + "nchannels", &nchannels, + NULL); + + pa_cvolume_init(&v); + v.channels = p->record.spec.channels; + for (i = 0; i < nchannels; ++i) { + v.values[i] = (PA_VOLUME_NORM - PA_VOLUME_MUTED) * volume[i] / G_MAXUINT16; + SPICE_DEBUG("record volume changed %u", v.values[i]); + } + + if (!p->record.stream || + pa_stream_get_device_index(p->record.stream) == PA_INVALID_INDEX) + return; + +#if PA_CHECK_VERSION(1,0,0) + op = pa_context_set_source_output_volume(p->context, + pa_stream_get_index(p->record.stream), +#else + op = pa_context_set_source_volume_by_index(p->context, + pa_stream_get_device_index(p->record.stream), +#endif + &v, NULL, NULL); + if (!op) + g_warning("set_source_output_volume() failed: %s", + pa_strerror(pa_context_errno(p->context))); + else + pa_operation_unref(op); +} + +static void +channel_weak_notified(gpointer data, + GObject *where_the_object_was) +{ + SpicePulse *pulse = SPICE_PULSE(data); + SpicePulsePrivate *p = pulse->priv; + + if (where_the_object_was == (GObject *)p->pchannel) { + SPICE_DEBUG("playback closed"); + playback_stop(pulse); + p->pchannel = NULL; + } else if (where_the_object_was == (GObject *)p->rchannel) { + SPICE_DEBUG("record closed"); + record_stop(pulse); + p->rchannel = NULL; + } +} + +static gboolean connect_channel(SpiceAudio *audio, SpiceChannel *channel) +{ + SpicePulse *pulse = SPICE_PULSE(audio); + SpicePulsePrivate *p = pulse->priv; + + if (SPICE_IS_PLAYBACK_CHANNEL(channel)) { + g_return_val_if_fail(p->pchannel == NULL, FALSE); + + p->pchannel = channel; + g_object_weak_ref(G_OBJECT(p->pchannel), channel_weak_notified, audio); + spice_g_signal_connect_object(channel, "playback-start", + G_CALLBACK(playback_start), pulse, 0); + spice_g_signal_connect_object(channel, "playback-data", + G_CALLBACK(playback_data), pulse, 0); + spice_g_signal_connect_object(channel, "playback-stop", + G_CALLBACK(playback_stop), pulse, G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "notify::volume", + G_CALLBACK(playback_volume_changed), pulse, 0); + spice_g_signal_connect_object(channel, "notify::mute", + G_CALLBACK(playback_mute_changed), pulse, 0); + spice_g_signal_connect_object(channel, "notify::min-latency", + G_CALLBACK(playback_min_latency_changed), pulse, 0); + + return TRUE; + } + + if (SPICE_IS_RECORD_CHANNEL(channel)) { + g_return_val_if_fail(p->rchannel == NULL, FALSE); + + p->rchannel = channel; + g_object_weak_ref(G_OBJECT(p->rchannel), channel_weak_notified, audio); + spice_g_signal_connect_object(channel, "record-start", + G_CALLBACK(record_start), pulse, 0); + spice_g_signal_connect_object(channel, "record-stop", + G_CALLBACK(record_stop), pulse, G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "notify::volume", + G_CALLBACK(record_volume_changed), pulse, 0); + spice_g_signal_connect_object(channel, "notify::mute", + G_CALLBACK(record_mute_changed), pulse, 0); + + return TRUE; + } + + return FALSE; +} + +static void context_state_callback(pa_context *c, void *userdata) +{ + SpicePulse *pulse = userdata; + SpicePulsePrivate *p; + + p = pulse->priv; + + g_return_if_fail(p != NULL); + g_return_if_fail(c != NULL); + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + case PA_CONTEXT_UNCONNECTED: + break; + + case PA_CONTEXT_READY: { + if (!p->record.stream && p->record.started) + create_record(SPICE_PULSE(userdata)); + + if (!p->playback.stream && p->playback.started) + create_playback(SPICE_PULSE(userdata)); + + if (p->pending_restore_task != NULL && + p->pending_restore_task->pa_op == NULL) { + pa_operation *op = pa_ext_stream_restore_read(p->context, + stream_restore_read_cb, + pulse); + if (!op) + goto context_fail; + p->pending_restore_task->pa_op = op; + } + break; + } + + case PA_CONTEXT_FAILED: + g_warning("PulseAudio context failed %s", + pa_strerror(pa_context_errno(p->context))); + goto context_fail; + + case PA_CONTEXT_TERMINATED: + default: + SPICE_DEBUG("PulseAudio context terminated"); + goto context_fail; + } + + return; + +context_fail: + if (p->pending_restore_task != NULL) { + const gchar *errmsg = pa_strerror(pa_context_errno(p->context)); + errmsg = (errmsg != NULL) ? errmsg : "PulseAudio context terminated"; + spice_pulse_complete_all_async_tasks(pulse, errmsg); + } +} + +SpicePulse *spice_pulse_new(SpiceSession *session, GMainContext *context, + const char *name) +{ + SpicePulse *pulse; + SpicePulsePrivate *p; + + pulse = g_object_new(SPICE_TYPE_PULSE, + "session", session, + "main-context", context, + NULL); + p = pulse->priv; + + p->mainloop = pa_glib_mainloop_new(context); + p->state = PA_CONTEXT_READY; + p->context = pa_context_new(pa_glib_mainloop_get_api(p->mainloop), name); + pa_context_set_state_callback(p->context, context_state_callback, pulse); + if (pa_context_connect(p->context, NULL, 0, NULL) < 0) { + g_warning("pa_context_connect() failed: %s", + pa_strerror(pa_context_errno(p->context))); + goto error; + } + + p->playback.name = g_strconcat("sink-input-by-application-name:", + g_get_application_name(), NULL); + p->record.name = g_strconcat("source-output-by-application-name:", + g_get_application_name(), NULL); + return pulse; + +error: + g_object_unref(pulse); + return NULL; +} + +static gboolean free_async_task(gpointer user_data) +{ + struct async_task *task = user_data; + + if (task == NULL) + return G_SOURCE_REMOVE; + + if (task->pa_op != NULL) { + pa_operation_cancel(task->pa_op); + g_clear_pointer(&task->pa_op, pa_operation_unref); + } + + if (task->pulse) { + if (task->pulse->priv->pending_restore_task == task) { + task->pulse->priv->pending_restore_task = NULL; + } + g_object_unref(task->pulse); + } + + if (task->main_channel) + g_object_unref(task->main_channel); + + if (task->pa_op != NULL) + pa_operation_unref(task->pa_op); + + g_cancellable_disconnect(g_task_get_cancellable(task->gtask), task->cancel_id); + + if (task->gtask) + g_object_unref(task->gtask); + + g_free(task); + return G_SOURCE_REMOVE; +} + +static void cancel_task(GCancellable *cancellable, gpointer user_data) +{ + struct async_task *task = user_data; + g_return_if_fail(task != NULL); + +#if GLIB_CHECK_VERSION(2,40,0) + free_async_task(task); +#else + /* This must be done now otherwise pulseaudio may return to a + * cancelled task operation before free_async_task is called */ + if (task->pa_op != NULL) { + pa_operation_cancel(task->pa_op); + g_clear_pointer(&task->pa_op, pa_operation_unref); + } + + /* Clear the pending_restore_task reference to avoid triggering a + * pa_operation when context state is in READY state */ + if (task->pulse->priv->pending_restore_task == task) { + task->pulse->priv->pending_restore_task = NULL; + } + + /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=705395 + * Free the memory in idle */ + g_idle_add(free_async_task, task); +#endif +} + +static void complete_task(SpicePulse *pulse, struct async_task *task, const gchar *err_msg) +{ + SpicePulsePrivate *p = pulse->priv; + + /* If we do have any err_msg, we failed */ + if (err_msg != NULL) { + g_task_return_new_error(task->gtask, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "restore-info failed: %s", + err_msg); + /* Volume-info does not change if stream is not found */ + } else if ((task->is_playback == TRUE && p->playback.info_updated == FALSE) || + (task->is_playback == FALSE && p->record.info_updated == FALSE)) { + g_task_return_new_error(task->gtask, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "Stream not found by pulse"); + } else { + g_task_return_boolean(task->gtask, TRUE); + } +} + +static void spice_pulse_complete_async_task(struct async_task *task, const gchar *err_msg) +{ + SpicePulsePrivate *p; + + g_return_if_fail(task != NULL); + p = task->pulse->priv; + + complete_task(task->pulse, task, err_msg); + if (p->results != NULL) { + p->results = g_list_remove(p->results, task); + SPICE_DEBUG("Number of async task is %u", g_list_length(p->results)); + } + free_async_task(task); +} + +static void spice_pulse_complete_all_async_tasks(SpicePulse *pulse, const gchar *err_msg) +{ + SpicePulsePrivate *p; + GList *it; + + g_return_if_fail(pulse != NULL); + p = pulse->priv; + + /* Complete all tasks in list */ + for(it = p->results; it != NULL; it = it->next) { + struct async_task *task = it->data; + complete_task(pulse, task, err_msg); + free_async_task(task); + } + g_clear_pointer(&p->results, g_list_free); + SPICE_DEBUG("All async tasks completed"); +} + +static void stream_restore_read_cb(pa_context *context, + const pa_ext_stream_restore_info *info, + int eol, + void *userdata) +{ + SpicePulsePrivate *p = SPICE_PULSE(userdata)->priv; + struct stream *pstream = NULL; + + if (eol || + (p->playback.info_updated == TRUE && + p->record.info_updated == TRUE)) { + /* We only have one pa_operation running the stream-restore-info + * which retrieves volume-info from both Playback and Record channels; + * We can complete all async tasks now that this operation ended. + * (or we already have the volume-info we want) + * Note: the following function cancel the current pa_operation */ + spice_pulse_complete_all_async_tasks(SPICE_PULSE(userdata), NULL); + return; + } + + if (g_strcmp0(info->name, p->playback.name) == 0) { + pstream = &p->playback; + } else if (g_strcmp0(info->name, p->record.name) == 0) { + pstream = &p->record; + } else { + /* This is not the stream you are looking for. */ + return; + } + + if (info->channel_map.channels == 0) { + SPICE_DEBUG("Number of channels stored is zero. Ignore. (%s)", info->name); + return; + } + + pstream->info_updated = TRUE; + pstream->info.name = pstream->name; + pstream->info.mute = info->mute; + pstream->info.channel_map = info->channel_map; + pstream->info.volume = info->volume; +} + +#if PA_CHECK_VERSION(1,0,0) +static void source_output_info_cb(pa_context *context, + const pa_source_output_info *info, + int eol, + void *userdata) +#else +static void source_info_cb(pa_context *context, + const pa_source_info *info, + int eol, + void *userdata) +#endif +{ + struct async_task *task = userdata; + SpicePulsePrivate *p = task->pulse->priv; + struct stream *pstream = &p->record; + + if (eol) { + spice_pulse_complete_async_task(task, NULL); + return; + } + + pstream->info_updated = TRUE; + pstream->info.name = pstream->name; + pstream->info.mute = info->mute; + pstream->info.channel_map = info->channel_map; + pstream->info.volume = info->volume; +} + +static void sink_input_info_cb(pa_context *context, + const pa_sink_input_info *info, + int eol, + void *userdata) +{ + struct async_task *task = userdata; + SpicePulsePrivate *p = task->pulse->priv; + struct stream *pstream = &p->playback; + + if (eol) { + spice_pulse_complete_async_task(task, NULL); + return; + } + + pstream->info_updated = TRUE; + pstream->info.name = pstream->name; + pstream->info.mute = info->mute; + pstream->info.channel_map = info->channel_map; + pstream->info.volume = info->volume; +} + +/* to avoid code duplication */ +static void pulse_stream_restore_info_async(gboolean is_playback, + SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpicePulsePrivate *p = SPICE_PULSE(audio)->priv; + GTask *gtask; + struct async_task *task = g_malloc0(sizeof(struct async_task)); + pa_operation *op = NULL; + + gtask = g_task_new(audio, cancellable, callback, user_data); + + task->gtask = gtask; + task->pulse = g_object_ref(audio); + task->callback = callback; + task->user_data = user_data; + task->is_playback = is_playback; + task->main_channel = g_object_ref(main_channel); + task->pa_op = NULL; + + if (cancellable) + task->cancel_id = g_cancellable_connect(cancellable, G_CALLBACK(cancel_task), task, NULL); + + /* If Playback/Record stream is created we use pulse API to get volume-info + * from those streams directly. If the stream is not created, retrieve last + * volume/mute values from Pulse database using the application name; + * If we already have retrieved volume-info from Pulse database then it is + * safe to return the volume-info we already have in info */ + + if (is_playback == TRUE && + p->playback.stream != NULL && + pa_stream_get_index(p->playback.stream) != PA_INVALID_INDEX) { + SPICE_DEBUG("Playback stream is created - get-sink-input-info"); + p->playback.info_updated = FALSE; + op = pa_context_get_sink_input_info(p->context, + pa_stream_get_index(p->playback.stream), + sink_input_info_cb, + task); + if (!op) + goto fail; + task->pa_op = op; + + } else if (is_playback == FALSE && + p->record.stream != NULL && + pa_stream_get_index(p->record.stream) != PA_INVALID_INDEX) { + SPICE_DEBUG("Record stream is created - get-source-output-info"); + p->record.info_updated = FALSE; +#if PA_CHECK_VERSION(1,0,0) + op = pa_context_get_source_output_info(p->context, + pa_stream_get_index(p->record.stream), + source_output_info_cb, + task); +#else + op = pa_context_get_source_info_by_index(p->context, + pa_stream_get_device_index(p->record.stream), + source_info_cb, + task); +#endif + if (!op) + goto fail; + task->pa_op = op; + + } else { + if (p->playback.info.name != NULL || + p->record.info.name != NULL) { + /* If the pstream->info.name is set then we already have updated + * volume information. We can complete the request now */ + SPICE_DEBUG("Return the volume-information we already have"); + spice_pulse_complete_async_task(task, NULL); + return; + } + + if (p->results == NULL) { + SPICE_DEBUG("Streams are not created - ext-stream-restore"); + p->playback.info_updated = FALSE; + p->record.info_updated = FALSE; + + if (pa_context_get_state(p->context) == PA_CONTEXT_READY) { + /* Restore value from pulse db */ + op = pa_ext_stream_restore_read(p->context, stream_restore_read_cb, audio); + if (!op) + goto fail; + task->pa_op = op; + } else { + /* It is possible that we want to get volume-info before the + * context is in READY state. In this case, we wait for the + * context state change to READY. */ + p->pending_restore_task = task; + } + } + } + + p->results = g_list_append(p->results, task); + SPICE_DEBUG ("Number of async task is %u", g_list_length(p->results)); + return; + +fail: + if (!op) { + g_task_report_new_error(audio, + callback, + user_data, + pulse_stream_restore_info_async, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "Volume-Info failed: %s", + pa_strerror(pa_context_errno(p->context))); + free_async_task(task); + } +} + +/* to avoid code duplication */ +static gboolean pulse_stream_restore_info_finish(gboolean is_playback, + SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + SpicePulsePrivate *p = SPICE_PULSE(audio)->priv; + struct stream *pstream = (is_playback) ? &p->playback : &p->record; + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, G_OBJECT(audio)), FALSE); + + if (g_task_had_error(task)) { + /* set out args that should have new alloc'ed memory to NULL */ + if (volume != NULL) { + *volume = NULL; + } + return g_task_propagate_boolean(task, error); + } + + if (mute != NULL) { + *mute = (pstream->info.mute) ? TRUE : FALSE; + } + + if (nchannels != NULL) { + *nchannels = pstream->info.channel_map.channels; + } + + if (volume != NULL) { + gint i; + *volume = g_new(guint16, pstream->info.channel_map.channels); + for (i = 0; i < pstream->info.channel_map.channels; i++) { + (*volume)[i] = MIN(pstream->info.volume.values[i], G_MAXUINT16); + SPICE_DEBUG("(%s) volume at channel %d is %u", + (is_playback) ? "playback" : "record", i, (*volume)[i]); + } + } + + return g_task_propagate_boolean(task, error); +} + +static void spice_pulse_get_playback_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + pulse_stream_restore_info_async(TRUE, audio, cancellable, main_channel, callback, user_data); +} + +static gboolean spice_pulse_get_playback_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + return pulse_stream_restore_info_finish(TRUE, audio, res, mute, + nchannels, volume, error); +} + +static void spice_pulse_get_record_volume_info_async(SpiceAudio *audio, + GCancellable *cancellable, + SpiceMainChannel *main_channel, + GAsyncReadyCallback callback, + gpointer user_data) +{ + pulse_stream_restore_info_async(FALSE, audio, cancellable, main_channel, callback, user_data); +} + +static gboolean spice_pulse_get_record_volume_info_finish(SpiceAudio *audio, + GAsyncResult *res, + gboolean *mute, + guint8 *nchannels, + guint16 **volume, + GError **error) +{ + return pulse_stream_restore_info_finish(FALSE, audio, res, mute, + nchannels, volume, error); +} diff --git a/src/spice-pulse.h b/src/spice-pulse.h new file mode 100644 index 0000000..819647e --- /dev/null +++ b/src/spice-pulse.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_PULSE_H__ +#define __SPICE_CLIENT_PULSE_H__ + +#include "spice-client.h" +#include "spice-audio.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_PULSE (spice_pulse_get_type()) +#define SPICE_PULSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_PULSE, SpicePulse)) +#define SPICE_PULSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_PULSE, SpicePulseClass)) +#define SPICE_IS_PULSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_PULSE)) +#define SPICE_IS_PULSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_PULSE)) +#define SPICE_PULSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_PULSE, SpicePulseClass)) + + +typedef struct _SpicePulse SpicePulse; +typedef struct _SpicePulseClass SpicePulseClass; +typedef struct _SpicePulsePrivate SpicePulsePrivate; + +struct _SpicePulse { + SpiceAudio parent; + SpicePulsePrivate *priv; + /* Do not add fields to this struct */ +}; + +struct _SpicePulseClass { + SpiceAudioClass parent_class; + /* Do not add fields to this struct */ +}; + +GType spice_pulse_get_type(void); + +SpicePulse *spice_pulse_new(SpiceSession *session, + GMainContext *context, + const char *name); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_PULSE_H__ */ diff --git a/src/spice-session-priv.h b/src/spice-session-priv.h new file mode 100644 index 0000000..049973a --- /dev/null +++ b/src/spice-session-priv.h @@ -0,0 +1,104 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_SESSION_PRIV_H__ +#define __SPICE_CLIENT_SESSION_PRIV_H__ + +#include "config.h" + +#include +#include + +#ifdef USE_PHODAV +#include +#else +typedef struct _PhodavServer PhodavServer; +#endif + +#include "desktop-integration.h" +#include "spice-session.h" +#include "spice-gtk-session.h" +#include "spice-channel-cache.h" +#include "decode.h" + +G_BEGIN_DECLS + +#define WEBDAV_MAGIC_SIZE 16 + +SpiceSession *spice_session_new_from_session(SpiceSession *session); + +void spice_session_set_connection_id(SpiceSession *session, int id); +int spice_session_get_connection_id(SpiceSession *session); +gboolean spice_session_get_client_provided_socket(SpiceSession *session); + +GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel, + gboolean *use_tls, GError **error); +void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel); +void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel); + +void spice_session_set_mm_time(SpiceSession *session, guint32 time); +guint32 spice_session_get_mm_time(SpiceSession *session); + +void spice_session_switching_disconnect(SpiceSession *session); +void spice_session_start_migrating(SpiceSession *session, + gboolean full_migration); +void spice_session_abort_migration(SpiceSession *session); +void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigration state); + +void spice_session_set_port(SpiceSession *session, int port, gboolean tls); +void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *size); +guint spice_session_get_verify(SpiceSession *session); +const gchar* spice_session_get_username(SpiceSession *session); +const gchar* spice_session_get_password(SpiceSession *session); +const gchar* spice_session_get_host(SpiceSession *session); +const gchar* spice_session_get_cert_subject(SpiceSession *session); +const gchar* spice_session_get_ciphers(SpiceSession *session); +const gchar* spice_session_get_ca_file(SpiceSession *session); +void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size); + +void spice_session_set_caches_hints(SpiceSession *session, + uint32_t pci_ram_size, + uint32_t n_display_channels); +void spice_session_get_caches(SpiceSession *session, + display_cache **images, + SpiceGlzDecoderWindow **glz_window); +void spice_session_palettes_clear(SpiceSession *session); +void spice_session_images_clear(SpiceSession *session); +void spice_session_migrate_end(SpiceSession *session); +gboolean spice_session_migrate_after_main_init(SpiceSession *session); +SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint type); +void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16]); +void spice_session_set_name(SpiceSession *session, const gchar *name); +gboolean spice_session_is_playback_active(SpiceSession *session); +guint32 spice_session_get_playback_latency(SpiceSession *session); +void spice_session_sync_playback_latency(SpiceSession *session); +const gchar* spice_session_get_shared_dir(SpiceSession *session); +void spice_session_set_shared_dir(SpiceSession *session, const gchar *dir); +gboolean spice_session_get_audio_enabled(SpiceSession *session); +gboolean spice_session_get_smartcard_enabled(SpiceSession *session); +gboolean spice_session_get_usbredir_enabled(SpiceSession *session); + +const guint8* spice_session_get_webdav_magic(SpiceSession *session); +PhodavServer *spice_session_get_webdav_server(SpiceSession *session); +PhodavServer* channel_webdav_server_new(SpiceSession *session); +guint spice_session_get_n_display_channels(SpiceSession *session); +void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel); +gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session); +SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context); +G_END_DECLS + +#endif /* __SPICE_CLIENT_SESSION_PRIV_H__ */ diff --git a/src/spice-session.c b/src/spice-session.c new file mode 100644 index 0000000..db283d4 --- /dev/null +++ b/src/spice-session.c @@ -0,0 +1,2787 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#ifdef G_OS_UNIX +#include +#endif +#include "common/ring.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-channel-priv.h" +#include "spice-util-priv.h" +#include "spice-session-priv.h" +#include "gio-coroutine.h" +#include "wocky-http-proxy.h" +#include "spice-uri-priv.h" +#include "channel-playback-priv.h" +#include "spice-audio.h" + +struct channel { + SpiceChannel *channel; + RingItem link; +}; + +#define IMAGES_CACHE_SIZE_DEFAULT (1024 * 1024 * 80) +#define MIN_GLZ_WINDOW_SIZE_DEFAULT (1024 * 1024 * 12) +#define MAX_GLZ_WINDOW_SIZE_DEFAULT MIN((LZ_MAX_WINDOW_SIZE * 4), 1024 * 1024 * 64) + +struct _SpiceSessionPrivate { + char *host; + char *unix_path; + char *port; + char *tls_port; + char *username; + char *password; + char *ca_file; + char *ciphers; + GByteArray *pubkey; + GByteArray *ca; + char *cert_subject; + guint verify; + gboolean read_only; + SpiceURI *proxy; + gchar *shared_dir; + gboolean share_dir_ro; + + /* whether to enable audio */ + gboolean audio; + + /* whether to enable smartcard event forwarding to the server */ + gboolean smartcard; + + /* list of certificates to use for the software smartcard reader if + * enabled. For now, it has to contain exactly 3 certificates for + * the software reader to be functional + */ + GStrv smartcard_certificates; + + /* path to the local certificate database to use to lookup the + * certificates stored in 'certificates'. If NULL, libcacard will + * fallback to using a default database. + */ + char * smartcard_db; + + /* whether to enable USB redirection */ + gboolean usbredir; + + /* Set when a usbredir channel has requested the keyboard grab to be + temporarily released (because it is going to invoke policykit) */ + gboolean inhibit_keyboard_grab; + + GStrv disable_effects; + GStrv secure_channels; + gint color_depth; + + int connection_id; + int protocol; + SpiceChannel *cmain; /* weak reference */ + Ring channels; + guint32 mm_time; + gboolean client_provided_sockets; + guint64 mm_time_at_clock; + SpiceSession *migration; + GList *migration_left; + SpiceSessionMigration migration_state; + gboolean full_migration; /* seamless migration indicator */ + guint disconnecting; + gboolean migrate_wait_init; + guint after_main_init; + gboolean for_migration; + + display_cache *images; + display_cache *palettes; + SpiceGlzDecoderWindow *glz_window; + int images_cache_size; + int glz_window_size; + uint32_t pci_ram_size; + uint32_t n_display_channels; + guint8 uuid[16]; + gchar *name; + SpiceImageCompression preferred_compression; + + /* associated objects */ + SpiceAudio *audio_manager; + SpiceUsbDeviceManager *usb_manager; + SpicePlaybackChannel *playback_channel; + PhodavServer *webdav; +}; + + +/** + * SECTION:spice-session + * @short_description: handles connection details, and active channels + * @title: Spice Session + * @section_id: + * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay + * @stability: Stable + * @include: spice-client.h + * + * The #SpiceSession class handles all the #SpiceChannel connections. + * It's also the class that contains connections informations, such as + * #SpiceSession:host and #SpiceSession:port. + * + * You can simply set the property #SpiceSession:uri to something like + * "spice://127.0.0.1?port=5930" to configure your connection details. + * + * You may want to connect to #SpiceSession::channel-new signal, to be + * informed of the availability of channels and to interact with + * them. + * + * For example, when the #SpiceInputsChannel is available and get the + * event #SPICE_CHANNEL_OPENED, you can send key events with + * spice_inputs_key_press(). When the #SpiceMainChannel is available, + * you can start sharing the clipboard... . + * + * + * Once #SpiceSession properties set, you can call + * spice_session_connect() to start connecting and communicating with + * a Spice server. + */ + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_SESSION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_SESSION, SpiceSessionPrivate)) + +G_DEFINE_TYPE (SpiceSession, spice_session, G_TYPE_OBJECT); + +/* Properties */ +enum { + PROP_0, + PROP_HOST, + PROP_PORT, + PROP_TLS_PORT, + PROP_PASSWORD, + PROP_CA_FILE, + PROP_CIPHERS, + PROP_IPV4, + PROP_IPV6, + PROP_PROTOCOL, + PROP_URI, + PROP_CLIENT_SOCKETS, + PROP_PUBKEY, + PROP_CERT_SUBJECT, + PROP_VERIFY, + PROP_MIGRATION_STATE, + PROP_AUDIO, + PROP_SMARTCARD, + PROP_SMARTCARD_CERTIFICATES, + PROP_SMARTCARD_DB, + PROP_USBREDIR, + PROP_INHIBIT_KEYBOARD_GRAB, + PROP_DISABLE_EFFECTS, + PROP_COLOR_DEPTH, + PROP_READ_ONLY, + PROP_CACHE_SIZE, + PROP_GLZ_WINDOW_SIZE, + PROP_UUID, + PROP_NAME, + PROP_CA, + PROP_PROXY, + PROP_SECURE_CHANNELS, + PROP_SHARED_DIR, + PROP_SHARE_DIR_RO, + PROP_USERNAME, + PROP_UNIX_PATH, + PROP_PREF_COMPRESSION, +}; + +/* signals */ +enum { + SPICE_SESSION_CHANNEL_NEW, + SPICE_SESSION_CHANNEL_DESTROY, + SPICE_SESSION_MM_TIME_RESET, + SPICE_SESSION_LAST_SIGNAL, +}; + +/* Register SpiceImageCompress */ +#define SPICE_TYPE_IMAGE_COMPRESSION spice_image_compress_get_type() +GType spice_image_compress_get_type (void); + +static const GEnumValue _spice_image_compress_values[] = { + { SPICE_IMAGE_COMPRESSION_INVALID, "SPICE_IMAGE_COMPRESSION_INVALID", "invalid" }, + { SPICE_IMAGE_COMPRESSION_OFF, "SPICE_IMAGE_COMPRESSION_OFF", "off" }, + { SPICE_IMAGE_COMPRESSION_AUTO_GLZ, "SPICE_IMAGE_COMPRESSION_AUTO_GLZ", "auto-glz" }, + { SPICE_IMAGE_COMPRESSION_AUTO_LZ, "SPICE_IMAGE_COMPRESSION_AUTO_LZ", "auto-lz" }, + { SPICE_IMAGE_COMPRESSION_QUIC, "SPICE_IMAGE_COMPRESSION_QUIC", "quic" }, + { SPICE_IMAGE_COMPRESSION_GLZ, "SPICE_IMAGE_COMPRESSION_GLZ", "glz" }, + { SPICE_IMAGE_COMPRESSION_LZ, "SPICE_IMAGE_COMPRESSION_LZ", "lz" }, + { SPICE_IMAGE_COMPRESSION_LZ4, "SPICE_IMAGE_COMPRESSION_LZ4", "lz4" }, + { 0, NULL, NULL } +}; + +G_STATIC_ASSERT(G_N_ELEMENTS(_spice_image_compress_values) == SPICE_IMAGE_COMPRESSION_ENUM_END + 1); + +GType +spice_image_compress_get_type (void) +{ + static GType type = 0; + static volatile gsize type_volatile = 0; + + if (g_once_init_enter(&type_volatile)) { + type = g_enum_register_static ("SpiceImageCompress", _spice_image_compress_values); + g_once_init_leave(&type_volatile, type); + } + + return type; +} + +static guint signals[SPICE_SESSION_LAST_SIGNAL]; + +static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel); + +static void update_proxy(SpiceSession *self, const gchar *str) +{ + SpiceSessionPrivate *s = self->priv; + SpiceURI *proxy = NULL; + GError *error = NULL; + + if (str == NULL) + str = g_getenv("SPICE_PROXY"); + if (str == NULL || *str == 0) { + g_clear_object(&s->proxy); + return; + } + + proxy = spice_uri_new(); + if (!spice_uri_parse(proxy, str, &error)) + g_clear_object(&proxy); + if (error) { + g_warning("%s", error->message); + g_clear_error(&error); + } + + if (proxy != NULL) { + g_clear_object(&s->proxy); + s->proxy = proxy; + } +} + +static void spice_session_init(SpiceSession *session) +{ + SpiceSessionPrivate *s; + gchar *channels; + + SPICE_DEBUG("New session (compiled from package " PACKAGE_STRING ")"); + s = session->priv = SPICE_SESSION_GET_PRIVATE(session); + + channels = spice_channel_supported_string(); + SPICE_DEBUG("Supported channels: %s", channels); + g_free(channels); + + ring_init(&s->channels); + s->images = cache_image_new((GDestroyNotify)pixman_image_unref); + s->glz_window = glz_decoder_window_new(); + update_proxy(session, NULL); +} + +static void +session_disconnect(SpiceSession *self, gboolean keep_main) +{ + SpiceSessionPrivate *s; + struct channel *item; + RingItem *ring, *next; + + s = self->priv; + + for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) { + next = ring_next(&s->channels, ring); + item = SPICE_CONTAINEROF(ring, struct channel, link); + + if (keep_main && item->channel == s->cmain) { + spice_channel_disconnect(item->channel, SPICE_CHANNEL_NONE); + } else { + spice_session_channel_destroy(self, item->channel); + } + } + + s->connection_id = 0; + + g_clear_pointer(&s->name, g_free); + memset(s->uuid, 0, sizeof(s->uuid)); + + spice_session_abort_migration(self); +} + +static void +spice_session_dispose(GObject *gobject) +{ + SpiceSession *session = SPICE_SESSION(gobject); + SpiceSessionPrivate *s = session->priv; + + SPICE_DEBUG("session dispose"); + + session_disconnect(session, FALSE); + + g_warn_if_fail(s->migration == NULL); + g_warn_if_fail(s->migration_left == NULL); + g_warn_if_fail(s->after_main_init == 0); + g_warn_if_fail(s->disconnecting == 0); + + g_clear_object(&s->audio_manager); + g_clear_object(&s->usb_manager); + g_clear_object(&s->proxy); + g_clear_object(&s->webdav); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_session_parent_class)->dispose) + G_OBJECT_CLASS(spice_session_parent_class)->dispose(gobject); +} + +static void +spice_session_finalize(GObject *gobject) +{ + SpiceSession *session = SPICE_SESSION(gobject); + SpiceSessionPrivate *s = session->priv; + + /* release stuff */ + g_free(s->unix_path); + g_free(s->host); + g_free(s->port); + g_free(s->tls_port); + g_free(s->username); + g_free(s->password); + g_free(s->ca_file); + g_free(s->ciphers); + g_free(s->cert_subject); + g_strfreev(s->smartcard_certificates); + g_free(s->smartcard_db); + g_strfreev(s->disable_effects); + g_strfreev(s->secure_channels); + g_free(s->shared_dir); + + g_clear_pointer(&s->images, cache_free); + glz_decoder_window_destroy(s->glz_window); + + g_clear_pointer(&s->pubkey, g_byte_array_unref); + g_clear_pointer(&s->ca, g_byte_array_unref); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_session_parent_class)->finalize) + G_OBJECT_CLASS(spice_session_parent_class)->finalize(gobject); +} + +#define URI_SCHEME_SPICE "spice://" +#define URI_SCHEME_SPICE_UNIX "spice+unix://" +#define URI_QUERY_START ";?" +#define URI_QUERY_SEP ";&" + +static gchar* spice_uri_create(SpiceSession *session) +{ + SpiceSessionPrivate *s = session->priv; + + if (s->unix_path != NULL) { + return g_strdup_printf(URI_SCHEME_SPICE_UNIX "%s", s->unix_path); + } else if (s->host != NULL) { + g_return_val_if_fail(s->port != NULL || s->tls_port != NULL, NULL); + + GString *str = g_string_new(URI_SCHEME_SPICE); + + g_string_append(str, s->host); + g_string_append(str, "?"); + if (s->port != NULL) { + g_string_append_printf(str, "port=%s&", s->port); + } + if (s->tls_port != NULL) { + g_string_append_printf(str, "tls-port=%s", s->tls_port); + } + return g_string_free(str, FALSE); + } + + g_return_val_if_reached(NULL); +} + +static int spice_parse_uri(SpiceSession *session, const char *original_uri) +{ + SpiceSessionPrivate *s = session->priv; + gchar *host = NULL, *port = NULL, *tls_port = NULL, *uri = NULL, *username = NULL, *password = NULL; + gchar *path = NULL; + gchar *authority = NULL; + gchar *query = NULL; + gchar *tmp = NULL; + + g_return_val_if_fail(original_uri != NULL, -1); + + uri = g_strdup(original_uri); + + if (g_str_has_prefix(uri, URI_SCHEME_SPICE_UNIX)) { + path = uri + strlen(URI_SCHEME_SPICE_UNIX); + goto end; + } + + /* Break up the URI into its various parts, scheme, authority, + * path (ignored) and query + */ + if (!g_str_has_prefix(uri, URI_SCHEME_SPICE)) { + g_warning("Expected a URI scheme of '%s' in URI '%s'", + URI_SCHEME_SPICE, uri); + goto fail; + } + authority = uri + strlen(URI_SCHEME_SPICE); + + tmp = strchr(authority, '@'); + if (tmp) { + tmp[0] = '\0'; + username = g_uri_unescape_string(authority, NULL); + authority = ++tmp; + tmp = NULL; + } + + path = strchr(authority, '/'); + if (path) { + path[0] = '\0'; + path++; + } + + if (path) { + size_t prefix = strcspn(path, URI_QUERY_START); + query = path + prefix; + } else { + size_t prefix = strcspn(authority, URI_QUERY_START); + query = authority + prefix; + } + + if (query && query[0]) { + query[0] = '\0'; + query++; + } + + /* Now process the individual parts */ + + if (authority[0] == '[') { + tmp = strchr(authority, ']'); + if (!tmp) { + g_warning("Missing closing ']' in authority for URI '%s'", uri); + goto fail; + } + tmp[0] = '\0'; + tmp++; + host = g_strdup_printf("[%s]", authority + 1); + if (tmp[0] == ':') + port = g_strdup(tmp + 1); + } else { + tmp = strchr(authority, ':'); + if (tmp) { + *tmp = '\0'; + tmp++; + port = g_strdup(tmp); + } + host = g_uri_unescape_string(authority, NULL); + } + + if (path && !(g_str_equal(path, "") || + g_str_equal(path, "/"))) { + g_warning("Unexpected path data '%s' for URI '%s'", path, uri); + /* don't fail, just ignore */ + } + path = NULL; + + while (query && query[0] != '\0') { + gchar key[32], value[128]; + gchar **target_key; + + int len; + if (sscanf(query, "%31[-a-zA-Z0-9]=%n", key, &len) != 1) { + g_warning("Failed to parse key in URI '%s'", query); + goto fail; + } + + query += len; + if (*query == '\0') { + SPICE_DEBUG("key '%s' without value", key); + break; + } else if (*query == ';' || *query == '&') { + /* another argument */ + query++; + continue; + } + + if (sscanf(query, "%127[^;&]%n", value, &len) != 1) { + g_warning("Failed to parse value of key '%s' in URI '%s'", key, query); + goto fail; + } + + query += len; + if (*query) + query++; + + target_key = NULL; + if (g_str_equal(key, "port")) { + target_key = &port; + } else if (g_str_equal(key, "tls-port")) { + target_key = &tls_port; + } else if (g_str_equal(key, "password")) { + target_key = &password; + g_warning("password may be visible in process listings"); + } else { + g_warning("unknown key in spice URI parsing: '%s'", key); + goto fail; + } + if (target_key) { + if (*target_key) { + g_warning("Double set of '%s' in URI '%s'", key, uri); + goto fail; + } + *target_key = g_uri_unescape_string(value, NULL); + } + } + + if (port == NULL && tls_port == NULL) { + g_warning("Missing port or tls-port in spice URI '%s'", uri); + goto fail; + } + +end: + /* parsed ok -> apply */ + g_free(s->unix_path); + g_free(s->host); + g_free(s->port); + g_free(s->tls_port); + g_free(s->username); + g_free(s->password); + s->unix_path = g_strdup(path); + g_free(uri); + s->host = host; + s->port = port; + s->tls_port = tls_port; + s->username = username; + s->password = password; + return 0; + +fail: + g_free(uri); + g_free(host); + g_free(port); + g_free(tls_port); + g_free(username); + g_free(password); + return -1; +} + +static void spice_session_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceSession *session = SPICE_SESSION(gobject); + SpiceSessionPrivate *s = session->priv; + + switch (prop_id) { + case PROP_HOST: + g_value_set_string(value, s->host); + break; + case PROP_UNIX_PATH: + g_value_set_string(value, s->unix_path); + break; + case PROP_PORT: + g_value_set_string(value, s->port); + break; + case PROP_TLS_PORT: + g_value_set_string(value, s->tls_port); + break; + case PROP_USERNAME: + g_value_set_string(value, s->username); + break; + case PROP_PASSWORD: + g_value_set_string(value, s->password); + break; + case PROP_CA_FILE: + g_value_set_string(value, s->ca_file); + break; + case PROP_CIPHERS: + g_value_set_string(value, s->ciphers); + break; + case PROP_PROTOCOL: + g_value_set_int(value, s->protocol); + break; + case PROP_URI: + g_value_take_string(value, spice_uri_create(session)); + break; + case PROP_CLIENT_SOCKETS: + g_value_set_boolean(value, s->client_provided_sockets); + break; + case PROP_PUBKEY: + g_value_set_boxed(value, s->pubkey); + break; + case PROP_CA: + g_value_set_boxed(value, s->ca); + break; + case PROP_CERT_SUBJECT: + g_value_set_string(value, s->cert_subject); + break; + case PROP_VERIFY: + g_value_set_flags(value, s->verify); + break; + case PROP_MIGRATION_STATE: + g_value_set_enum(value, s->migration_state); + break; + case PROP_SMARTCARD: + g_value_set_boolean(value, s->smartcard); + break; + case PROP_SMARTCARD_CERTIFICATES: + g_value_set_boxed(value, s->smartcard_certificates); + break; + case PROP_SMARTCARD_DB: + g_value_set_string(value, s->smartcard_db); + break; + case PROP_USBREDIR: + g_value_set_boolean(value, s->usbredir); + break; + case PROP_INHIBIT_KEYBOARD_GRAB: + g_value_set_boolean(value, s->inhibit_keyboard_grab); + break; + case PROP_DISABLE_EFFECTS: + g_value_set_boxed(value, s->disable_effects); + break; + case PROP_SECURE_CHANNELS: + g_value_set_boxed(value, s->secure_channels); + break; + case PROP_COLOR_DEPTH: + g_value_set_int(value, s->color_depth); + break; + case PROP_AUDIO: + g_value_set_boolean(value, s->audio); + break; + case PROP_READ_ONLY: + g_value_set_boolean(value, s->read_only); + break; + case PROP_CACHE_SIZE: + g_value_set_int(value, s->images_cache_size); + break; + case PROP_GLZ_WINDOW_SIZE: + g_value_set_int(value, s->glz_window_size); + break; + case PROP_NAME: + g_value_set_string(value, s->name); + break; + case PROP_UUID: + g_value_set_pointer(value, s->uuid); + break; + case PROP_PROXY: + g_value_take_string(value, spice_uri_to_string(s->proxy)); + break; + case PROP_SHARED_DIR: + g_value_set_string(value, spice_session_get_shared_dir(session)); + break; + case PROP_SHARE_DIR_RO: + g_value_set_boolean(value, s->share_dir_ro); + break; + case PROP_PREF_COMPRESSION: + g_value_set_enum(value, s->preferred_compression); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_session_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceSession *session = SPICE_SESSION(gobject); + SpiceSessionPrivate *s = session->priv; + const char *str; + + switch (prop_id) { + case PROP_HOST: + g_free(s->host); + s->host = g_value_dup_string(value); + break; + case PROP_UNIX_PATH: + g_free(s->unix_path); + s->unix_path = g_value_dup_string(value); + break; + case PROP_PORT: + g_free(s->port); + s->port = g_value_dup_string(value); + break; + case PROP_TLS_PORT: + g_free(s->tls_port); + s->tls_port = g_value_dup_string(value); + break; + case PROP_USERNAME: + g_free(s->username); + s->username = g_value_dup_string(value); + break; + case PROP_PASSWORD: + g_free(s->password); + s->password = g_value_dup_string(value); + break; + case PROP_CA_FILE: + g_free(s->ca_file); + s->ca_file = g_value_dup_string(value); + break; + case PROP_CIPHERS: + g_free(s->ciphers); + s->ciphers = g_value_dup_string(value); + break; + case PROP_PROTOCOL: + s->protocol = g_value_get_int(value); + break; + case PROP_URI: + str = g_value_get_string(value); + if (str != NULL) + spice_parse_uri(session, str); + break; + case PROP_CLIENT_SOCKETS: + s->client_provided_sockets = g_value_get_boolean(value); + break; + case PROP_PUBKEY: + if (s->pubkey) + g_byte_array_unref(s->pubkey); + s->pubkey = g_value_dup_boxed(value); + if (s->pubkey) + s->verify |= SPICE_SESSION_VERIFY_PUBKEY; + else + s->verify &= ~SPICE_SESSION_VERIFY_PUBKEY; + break; + case PROP_CERT_SUBJECT: + g_free(s->cert_subject); + s->cert_subject = g_value_dup_string(value); + if (s->cert_subject) + s->verify |= SPICE_SESSION_VERIFY_SUBJECT; + else + s->verify &= ~SPICE_SESSION_VERIFY_SUBJECT; + break; + case PROP_VERIFY: + s->verify = g_value_get_flags(value); + break; + case PROP_MIGRATION_STATE: + s->migration_state = g_value_get_enum(value); + break; + case PROP_SMARTCARD: + s->smartcard = g_value_get_boolean(value); + break; + case PROP_SMARTCARD_CERTIFICATES: + g_strfreev(s->smartcard_certificates); + s->smartcard_certificates = g_value_dup_boxed(value); + break; + case PROP_SMARTCARD_DB: + g_free(s->smartcard_db); + s->smartcard_db = g_value_dup_string(value); + break; + case PROP_USBREDIR: + s->usbredir = g_value_get_boolean(value); + break; + case PROP_INHIBIT_KEYBOARD_GRAB: + s->inhibit_keyboard_grab = g_value_get_boolean(value); + break; + case PROP_DISABLE_EFFECTS: + g_strfreev(s->disable_effects); + s->disable_effects = g_value_dup_boxed(value); + break; + case PROP_SECURE_CHANNELS: + g_strfreev(s->secure_channels); + s->secure_channels = g_value_dup_boxed(value); + break; + case PROP_COLOR_DEPTH: + s->color_depth = g_value_get_int(value); + break; + case PROP_AUDIO: + s->audio = g_value_get_boolean(value); + break; + case PROP_READ_ONLY: + s->read_only = g_value_get_boolean(value); + g_coroutine_object_notify(gobject, "read-only"); + break; + case PROP_CACHE_SIZE: + s->images_cache_size = g_value_get_int(value); + break; + case PROP_GLZ_WINDOW_SIZE: + s->glz_window_size = g_value_get_int(value); + break; + case PROP_CA: + g_clear_pointer(&s->ca, g_byte_array_unref); + s->ca = g_value_dup_boxed(value); + break; + case PROP_PROXY: + update_proxy(session, g_value_get_string(value)); + break; + case PROP_SHARED_DIR: + spice_session_set_shared_dir(session, g_value_get_string(value)); + break; + case PROP_SHARE_DIR_RO: + s->share_dir_ro = g_value_get_boolean(value); + break; + case PROP_PREF_COMPRESSION: + s->preferred_compression = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_session_class_init(SpiceSessionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + _wocky_http_proxy_get_type(); + _wocky_https_proxy_get_type(); + + gobject_class->dispose = spice_session_dispose; + gobject_class->finalize = spice_session_finalize; + gobject_class->get_property = spice_session_get_property; + gobject_class->set_property = spice_session_set_property; + + /** + * SpiceSession:host: + * + * URL of the SPICE host to connect to + * + **/ + g_object_class_install_property + (gobject_class, PROP_HOST, + g_param_spec_string("host", + "Host", + "Remote host", + "localhost", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:unix-path: + * + * Path of the Unix socket to connect to + * + * Since: 0.28 + **/ + g_object_class_install_property + (gobject_class, PROP_UNIX_PATH, + g_param_spec_string("unix-path", + "Unix path", + "Unix path", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:port: + * + * Port to connect to for unencrypted sessions + * + **/ + g_object_class_install_property + (gobject_class, PROP_PORT, + g_param_spec_string("port", + "Port", + "Remote port (plaintext)", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:tls-port: + * + * Port to connect to for TLS sessions + * + **/ + g_object_class_install_property + (gobject_class, PROP_TLS_PORT, + g_param_spec_string("tls-port", + "TLS port", + "Remote port (encrypted)", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:username: + * + * Username to use + * + **/ + g_object_class_install_property + (gobject_class, PROP_USERNAME, + g_param_spec_string("username", + "Username", + "Username used for SASL connections", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:password: + * + * TLS password to use + * + **/ + g_object_class_install_property + (gobject_class, PROP_PASSWORD, + g_param_spec_string("password", + "Password", + "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:ca-file: + * + * File holding the CA certificates for the host the client is + * connecting to + * + **/ + g_object_class_install_property + (gobject_class, PROP_CA_FILE, + g_param_spec_string("ca-file", + "CA file", + "File holding the CA certificates", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:ciphers: + * + **/ + g_object_class_install_property + (gobject_class, PROP_CIPHERS, + g_param_spec_string("ciphers", + "Ciphers", + "SSL cipher list", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:protocol: + * + * Version of the SPICE protocol to use + * + **/ + g_object_class_install_property + (gobject_class, PROP_PROTOCOL, + g_param_spec_int("protocol", + "Protocol", + "Spice protocol major version", + 1, 2, 2, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:uri: + * + * URI of the SPICE host to connect to. The URI is of the form + * spice://hostname?port=XXX or spice://hostname?tls_port=XXX + * + **/ + g_object_class_install_property + (gobject_class, PROP_URI, + g_param_spec_string("uri", + "URI", + "Spice connection URI", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:client-sockets: + * + **/ + g_object_class_install_property + (gobject_class, PROP_CLIENT_SOCKETS, + g_param_spec_boolean("client-sockets", + "Client sockets", + "Sockets are provided by the client", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:pubkey: + * + **/ + g_object_class_install_property + (gobject_class, PROP_PUBKEY, + g_param_spec_boxed("pubkey", + "Pub Key", + "Public key to check", + G_TYPE_BYTE_ARRAY, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:cert-subject: + * + **/ + g_object_class_install_property + (gobject_class, PROP_CERT_SUBJECT, + g_param_spec_string("cert-subject", + "Cert Subject", + "Certificate subject to check", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:verify: + * + * #SpiceSessionVerify bit field indicating which parts of the peer + * certificate should be checked + **/ + g_object_class_install_property + (gobject_class, PROP_VERIFY, + g_param_spec_flags("verify", + "Verify", + "Certificate verification parameters", + SPICE_TYPE_SESSION_VERIFY, + SPICE_SESSION_VERIFY_HOSTNAME, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:migration-state: + * + * #SpiceSessionMigration bit field indicating if a migration is in + * progress + * + **/ + g_object_class_install_property + (gobject_class, PROP_MIGRATION_STATE, + g_param_spec_enum("migration-state", + "Migration state", + "Migration state", + SPICE_TYPE_SESSION_MIGRATION, + SPICE_SESSION_MIGRATION_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:disable-effects: + * + * A string array of effects to disable. The settings will + * be applied on new display channels. The following effets can be + * disabled "wallpaper", "font-smooth", "animation", and "all", + * which will disable all the effects. If NULL, don't apply changes. + * + * Since: 0.7 + **/ + g_object_class_install_property + (gobject_class, PROP_DISABLE_EFFECTS, + g_param_spec_boxed ("disable-effects", + "Disable effects", + "Comma-separated effects to disable", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:color-depth: + * + * Display color depth to set on new display channels. If 0, don't set. + * + * Since: 0.7 + **/ + g_object_class_install_property + (gobject_class, PROP_COLOR_DEPTH, + g_param_spec_int("color-depth", + "Color depth", + "Display channel color depth", + 0, 32, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:enable-smartcard: + * + * If set to TRUE, the smartcard channel will be enabled and smartcard + * events will be forwarded to the guest + * + * Since: 0.7 + **/ + g_object_class_install_property + (gobject_class, PROP_SMARTCARD, + g_param_spec_boolean("enable-smartcard", + "Enable smartcard event forwarding", + "Forward smartcard events to the SPICE server", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:enable-audio: + * + * If set to TRUE, the audio channels will be enabled for + * playback and recording. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_AUDIO, + g_param_spec_boolean("enable-audio", + "Enable audio channels", + "Enable audio channels", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:smartcard-certificates: + * + * This property is used when one wants to simulate a smartcard with no + * hardware smartcard reader. If it's set to a NULL-terminated string + * array containing the names of 3 valid certificates, these will be + * used to simulate a smartcard in the guest + * See also spice_smartcard_manager_insert_card() + * + * Since: 0.7 + **/ + g_object_class_install_property + (gobject_class, PROP_SMARTCARD_CERTIFICATES, + g_param_spec_boxed("smartcard-certificates", + "Smartcard certificates", + "Smartcard certificates for software-based smartcards", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:smartcard-db: + * + * Path to the NSS certificate database containing the certificates to + * use to simulate a software smartcard + * + * Since: 0.7 + **/ + g_object_class_install_property + (gobject_class, PROP_SMARTCARD_DB, + g_param_spec_string("smartcard-db", + "Smartcard certificate database", + "Path to the database for smartcard certificates", + NULL, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:enable-usbredir: + * + * If set to TRUE, the usbredir channel will be enabled and USB devices + * can be redirected to the guest + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_USBREDIR, + g_param_spec_boolean("enable-usbredir", + "Enable USB device redirection", + "Forward USB devices to the SPICE server", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession::inhibit-keyboard-grab: + * + * This boolean is set by the usbredir channel to indicate to #SpiceDisplay + * that the keyboard grab should be temporarily released, because it is + * going to invoke policykit. It will get reset when the usbredir channel + * is done with polickit. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_INHIBIT_KEYBOARD_GRAB, + g_param_spec_boolean("inhibit-keyboard-grab", + "Inhibit Keyboard Grab", + "Request that SpiceDisplays don't grab the keyboard", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:ca: + * + * CA certificates in PEM format. The text data can contain + * several CA certificates identified by: + * + * -----BEGIN CERTIFICATE----- + * ... (CA certificate in base64 encoding) ... + * -----END CERTIFICATE----- + * + * Since: 0.15 + **/ + g_object_class_install_property + (gobject_class, PROP_CA, + g_param_spec_boxed("ca", + "CA", + "The CA certificates data", + G_TYPE_BYTE_ARRAY, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:secure-channels: + * + * A string array of channel types to be secured. + * + * Since: 0.20 + **/ + g_object_class_install_property + (gobject_class, PROP_SECURE_CHANNELS, + g_param_spec_boxed ("secure-channels", + "Secure channels", + "Array of channel type to secure", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + + /** + * SpiceSession::channel-new: + * @session: the session that emitted the signal + * @channel: the new #SpiceChannel + * + * The #SpiceSession::channel-new signal is emitted each time a #SpiceChannel is created. + **/ + signals[SPICE_SESSION_CHANNEL_NEW] = + g_signal_new("channel-new", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSessionClass, channel_new), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + SPICE_TYPE_CHANNEL); + + /** + * SpiceSession::channel-destroy: + * @session: the session that emitted the signal + * @channel: the destroyed #SpiceChannel + * + * The #SpiceSession::channel-destroy signal is emitted each time a #SpiceChannel is destroyed. + **/ + signals[SPICE_SESSION_CHANNEL_DESTROY] = + g_signal_new("channel-destroy", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceSessionClass, channel_destroy), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + SPICE_TYPE_CHANNEL); + + /** + * SpiceSession::mm-time-reset: + * @session: the session that emitted the signal + * + * The #SpiceSession::mm-time-reset is emitted when we identify discontinuity in mm-time + * + * Since 0.20 + **/ + signals[SPICE_SESSION_MM_TIME_RESET] = + g_signal_new("mm-time-reset", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * SpiceSession:read-only: + * + * Whether this connection is read-only mode. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_READ_ONLY, + g_param_spec_boolean("read-only", "Read-only", + "Whether this connection is read-only mode", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:cache-size: + * + * Images cache size. If 0, don't set. + * + * Since: 0.9 + **/ + g_object_class_install_property + (gobject_class, PROP_CACHE_SIZE, + g_param_spec_int("cache-size", + "Cache size", + "Images cache size (bytes)", + 0, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:glz-window-size: + * + * Glz window size. If 0, don't set. + * + * Since: 0.9 + **/ + g_object_class_install_property + (gobject_class, PROP_GLZ_WINDOW_SIZE, + g_param_spec_int("glz-window-size", + "Glz window size", + "Glz window size (bytes)", + 0, LZ_MAX_WINDOW_SIZE * 4, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:name: + * + * Spice server name. + * + * Since: 0.11 + **/ + g_object_class_install_property + (gobject_class, PROP_NAME, + g_param_spec_string("name", + "Name", + "Spice server name", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:uuid: + * + * Spice server uuid. + * + * Since: 0.11 + **/ + g_object_class_install_property + (gobject_class, PROP_UUID, + g_param_spec_pointer("uuid", + "UUID", + "Spice server uuid", + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:proxy: + * + * URI to the proxy server to use when doing network connection. + * of the form [:port] ]]> + * + * Since: 0.17 + **/ + g_object_class_install_property + (gobject_class, PROP_PROXY, + g_param_spec_string("proxy", + "Proxy", + "The proxy server", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:shared-dir: + * + * Location of the shared directory + * + * Since: 0.24 + **/ + g_object_class_install_property + (gobject_class, PROP_SHARED_DIR, + g_param_spec_string("shared-dir", + "Shared directory", + "Shared directory", + g_get_user_special_dir(G_USER_DIRECTORY_PUBLIC_SHARE), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:share-dir-ro: + * + * Whether to share the directory read-only. + * + * Since: 0.28 + **/ + g_object_class_install_property + (gobject_class, PROP_SHARE_DIR_RO, + g_param_spec_boolean("share-dir-ro", + "Share directory read-only", + "Share directory read-only", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceSession:preferred-compression: + * + * The image compression algorithm the client prefers to use. It is + * reported to the server. + * + * Since: 0.29 + **/ + g_object_class_install_property + (gobject_class, PROP_PREF_COMPRESSION, + g_param_spec_enum("preferred-compression", + "Preferred image compression algorithm", + "Preferred image compression algorithm", + SPICE_TYPE_IMAGE_COMPRESSION, + SPICE_IMAGE_COMPRESSION_INVALID, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private(klass, sizeof(SpiceSessionPrivate)); +} + +/* ------------------------------------------------------------------ */ +/* public functions */ + +/** + * spice_session_new: + * + * Creates a new Spice session. + * + * Returns: a new #SpiceSession + **/ +SpiceSession *spice_session_new(void) +{ + return SPICE_SESSION(g_object_new(SPICE_TYPE_SESSION, NULL)); +} + +G_GNUC_INTERNAL +SpiceSession *spice_session_new_from_session(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + SpiceSession *copy; + SpiceSessionPrivate *c; + + if (s->client_provided_sockets) { + g_warning("migration with client provided fd is not supported yet"); + return NULL; + } + + copy = SPICE_SESSION(g_object_new(SPICE_TYPE_SESSION, + "host", NULL, + "ca-file", NULL, + NULL)); + c = copy->priv; + g_clear_object(&c->proxy); + + g_warn_if_fail(c->host == NULL); + g_warn_if_fail(c->unix_path == NULL); + g_warn_if_fail(c->tls_port == NULL); + g_warn_if_fail(c->username == NULL); + g_warn_if_fail(c->password == NULL); + g_warn_if_fail(c->ca_file == NULL); + g_warn_if_fail(c->ciphers == NULL); + g_warn_if_fail(c->cert_subject == NULL); + g_warn_if_fail(c->pubkey == NULL); + g_warn_if_fail(c->pubkey == NULL); + g_warn_if_fail(c->proxy == NULL); + + g_object_get(session, + "host", &c->host, + "unix-path", &c->unix_path, + "tls-port", &c->tls_port, + "username", &c->username, + "password", &c->password, + "ca-file", &c->ca_file, + "ciphers", &c->ciphers, + "cert-subject", &c->cert_subject, + "pubkey", &c->pubkey, + "verify", &c->verify, + "smartcard-certificates", &c->smartcard_certificates, + "smartcard-db", &c->smartcard_db, + "enable-smartcard", &c->smartcard, + "enable-audio", &c->audio, + "enable-usbredir", &c->usbredir, + "ca", &c->ca, + NULL); + + c->client_provided_sockets = s->client_provided_sockets; + c->protocol = s->protocol; + c->connection_id = s->connection_id; + if (s->proxy) + c->proxy = g_object_ref(s->proxy); + + return copy; +} + +/** + * spice_session_connect: + * @session: a #SpiceSession + * + * Open the session using the #SpiceSession:host and + * #SpiceSession:port. + * + * Returns: %FALSE if the session state is invalid for connection + * request. %TRUE if the connection is initiated. To know whether the + * connection is established, you must watch for channels creation + * (#SpiceSession::channel-new) and the channels state + * (#SpiceChannel::channel-event). + **/ +gboolean spice_session_connect(SpiceSession *session) +{ + SpiceSessionPrivate *s; + + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + s = session->priv; + g_return_val_if_fail(!s->disconnecting, FALSE); + + session_disconnect(session, TRUE); + + s->client_provided_sockets = FALSE; + + if (s->cmain == NULL) + s->cmain = spice_channel_new(session, SPICE_CHANNEL_MAIN, 0); + + glz_decoder_window_clear(s->glz_window); + return spice_channel_connect(s->cmain); +} + +/** + * spice_session_open_fd: + * @session: a #SpiceSession + * @fd: a file descriptor (socket) or -1 + * + * Open the session using the provided @fd socket file + * descriptor. This is useful if you create the fd yourself, for + * example to setup a SSH tunnel. + * + * Note however that additional sockets will be needed by all the channels + * created for @session so users of this API should hook into + * SpiceChannel::open-fd signal for each channel they are interested in, and + * create and pass a new socket to the channel using #spice_channel_open_fd, in + * the signal callback. + * + * If @fd is -1, a valid fd will be requested later via the + * SpiceChannel::open-fd signal. Typically, you would want to just pass -1 as + * @fd this call since you will have to hook to SpiceChannel::open-fd signal + * anyway. + * + * Returns: %TRUE on success. + **/ +gboolean spice_session_open_fd(SpiceSession *session, int fd) +{ + SpiceSessionPrivate *s; + + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + g_return_val_if_fail(fd >= -1, FALSE); + + s = session->priv; + g_return_val_if_fail(!s->disconnecting, FALSE); + + session_disconnect(session, TRUE); + + s->client_provided_sockets = TRUE; + + if (s->cmain == NULL) + s->cmain = spice_channel_new(session, SPICE_CHANNEL_MAIN, 0); + + glz_decoder_window_clear(s->glz_window); + return spice_channel_open_fd(s->cmain, fd); +} + +G_GNUC_INTERNAL +gboolean spice_session_get_client_provided_socket(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + SpiceSessionPrivate *s = session->priv; + + return s->client_provided_sockets; +} + +static void cache_clear_all(SpiceSession *self) +{ + SpiceSessionPrivate *s = self->priv; + + cache_clear(s->images); + glz_decoder_window_clear(s->glz_window); +} + +G_GNUC_INTERNAL +void spice_session_switching_disconnect(SpiceSession *self) +{ + g_return_if_fail(SPICE_IS_SESSION(self)); + + SpiceSessionPrivate *s = self->priv; + struct channel *item; + RingItem *ring, *next; + + g_return_if_fail(s->cmain != NULL); + + /* disconnect/destroy all but main channel */ + + for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) { + next = ring_next(&s->channels, ring); + item = SPICE_CONTAINEROF(ring, struct channel, link); + + if (item->channel == s->cmain) + continue; + spice_session_channel_destroy(self, item->channel); + } + + g_warn_if_fail(!ring_is_empty(&s->channels)); /* ring_get_length() == 1 */ + + cache_clear_all(self); + s->connection_id = 0; +} + +#define SWAP_STR(x, y) G_STMT_START { \ + const gchar *tmp; \ + const gchar *a = x; \ + const gchar *b = y; \ + tmp = a; \ + a = b; \ + b = tmp; \ +} G_STMT_END + +G_GNUC_INTERNAL +void spice_session_start_migrating(SpiceSession *session, + gboolean full_migration) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + SpiceSessionPrivate *m; + + g_return_if_fail(s->migration != NULL); + m = s->migration->priv; + g_return_if_fail(m->migration_state == SPICE_SESSION_MIGRATION_CONNECTING); + + + s->full_migration = full_migration; + spice_session_set_migration_state(session, SPICE_SESSION_MIGRATION_MIGRATING); + + /* swapping connection details happens after MIGRATION_CONNECTING state */ + SWAP_STR(s->host, m->host); + SWAP_STR(s->port, m->port); + SWAP_STR(s->tls_port, m->tls_port); + SWAP_STR(s->unix_path, m->unix_path); + + g_warn_if_fail(ring_get_length(&s->channels) == ring_get_length(&m->channels)); + + SPICE_DEBUG("migration channels left:%u (in migration:%u)", + ring_get_length(&s->channels), ring_get_length(&m->channels)); + s->migration_left = spice_session_get_channels(session); +} +#undef SWAP_STR + +G_GNUC_INTERNAL +SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint type) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + RingItem *ring, *next; + SpiceSessionPrivate *s = session->priv; + struct channel *c; + + for (ring = ring_get_head(&s->channels); + ring != NULL; ring = next) { + next = ring_next(&s->channels, ring); + c = SPICE_CONTAINEROF(ring, struct channel, link); + if (c == NULL || c->channel == NULL) { + g_warn_if_reached(); + continue; + } + + if (id == spice_channel_get_channel_id(c->channel) && + type == spice_channel_get_channel_type(c->channel)) + break; + } + g_return_val_if_fail(ring != NULL, NULL); + + return c->channel; +} + +G_GNUC_INTERNAL +void spice_session_abort_migration(SpiceSession *session) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + RingItem *ring, *next; + struct channel *c; + + if (s->migration == NULL) { + SPICE_DEBUG("no migration in progress"); + return; + } + + SPICE_DEBUG("migration: abort"); + if (s->migration_state != SPICE_SESSION_MIGRATION_MIGRATING) + goto end; + + for (ring = ring_get_head(&s->channels); + ring != NULL; ring = next) { + next = ring_next(&s->channels, ring); + c = SPICE_CONTAINEROF(ring, struct channel, link); + + if (g_list_find(s->migration_left, c->channel)) + continue; + + spice_channel_swap(c->channel, + spice_session_lookup_channel(s->migration, + spice_channel_get_channel_id(c->channel), + spice_channel_get_channel_type(c->channel)), + !s->full_migration); + } + +end: + g_clear_pointer(&s->migration_left, g_list_free); + session_disconnect(s->migration, FALSE); + g_clear_pointer(&s->migration, g_object_unref); + + s->migrate_wait_init = FALSE; + if (s->after_main_init) { + g_source_remove(s->after_main_init); + s->after_main_init = 0; + } + + spice_session_set_migration_state(session, SPICE_SESSION_MIGRATION_NONE); +} + +G_GNUC_INTERNAL +void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + SpiceChannel *c; + gint id, type; + + g_return_if_fail(s->migration != NULL); + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + + id = spice_channel_get_channel_id(channel); + type = spice_channel_get_channel_type(channel); + CHANNEL_DEBUG(channel, "migrating channel id:%d type:%d", id, type); + + c = spice_session_lookup_channel(s->migration, id, type); + g_return_if_fail(c != NULL); + + if (!g_queue_is_empty(&c->priv->xmit_queue) && s->full_migration) { + CHANNEL_DEBUG(channel, "mig channel xmit queue is not empty. type %s", c->priv->name); + } + spice_channel_swap(channel, c, !s->full_migration); + s->migration_left = g_list_remove(s->migration_left, channel); + + if (g_list_length(s->migration_left) == 0) { + CHANNEL_DEBUG(channel, "migration: all channel migrated, success"); + session_disconnect(s->migration, FALSE); + g_clear_pointer(&s->migration, g_object_unref); + spice_session_set_migration_state(session, SPICE_SESSION_MIGRATION_NONE); + } +} + +/* main context */ +static gboolean after_main_init(gpointer data) +{ + SpiceSession *self = data; + SpiceSessionPrivate *s = self->priv; + GList *l; + + for (l = s->migration_left; l != NULL; ) { + SpiceChannel *channel = l->data; + l = l->next; + + spice_session_channel_migrate(self, channel); + channel->priv->state = SPICE_CHANNEL_STATE_READY; + spice_channel_up(channel); + } + + s->after_main_init = 0; + return FALSE; +} + +/* coroutine context */ +G_GNUC_INTERNAL +gboolean spice_session_migrate_after_main_init(SpiceSession *self) +{ + g_return_val_if_fail(SPICE_IS_SESSION(self), FALSE); + + SpiceSessionPrivate *s = self->priv; + + if (!s->migrate_wait_init) + return FALSE; + + g_return_val_if_fail(g_list_length(s->migration_left) != 0, FALSE); + g_return_val_if_fail(s->after_main_init == 0, FALSE); + + s->migrate_wait_init = FALSE; + s->after_main_init = g_idle_add(after_main_init, self); + + return TRUE; +} + +/* main context */ +G_GNUC_INTERNAL +void spice_session_migrate_end(SpiceSession *self) +{ + g_return_if_fail(SPICE_IS_SESSION(self)); + + SpiceSessionPrivate *s = self->priv; + SpiceMsgOut *out; + GList *l; + + g_return_if_fail(s->migration); + g_return_if_fail(s->migration->priv->cmain); + g_return_if_fail(g_list_length(s->migration_left) != 0); + + /* disconnect and reset all channels */ + for (l = s->migration_left; l != NULL; ) { + SpiceChannel *channel = l->data; + l = l->next; + + if (!SPICE_IS_MAIN_CHANNEL(channel)) { + /* freeze other channels */ + channel->priv->state = SPICE_CHANNEL_STATE_MIGRATING; + } + + /* reset for migration, disconnect */ + spice_channel_reset(channel, TRUE); + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + /* migrate main to target, so we can start talking */ + spice_session_channel_migrate(self, channel); + } + } + + cache_clear_all(self); + + /* send MIGRATE_END to target */ + out = spice_msg_out_new(s->cmain, SPICE_MSGC_MAIN_MIGRATE_END); + spice_msg_out_send(out); + + /* now wait after main init for the rest of channels migration */ + s->migrate_wait_init = TRUE; +} + +/** + * spice_session_get_read_only: + * @session: a #SpiceSession + * + * Checks whether the @session is read-only. + * + * Returns: whether the @session is in read-only mode. + **/ +gboolean spice_session_get_read_only(SpiceSession *self) +{ + g_return_val_if_fail(SPICE_IS_SESSION(self), FALSE); + + return self->priv->read_only; +} + +static gboolean session_disconnect_idle(SpiceSession *self) +{ + SpiceSessionPrivate *s = self->priv; + + session_disconnect(self, FALSE); + s->disconnecting = 0; + + g_object_unref(self); + + return FALSE; +} + +/** + * spice_session_disconnect: + * @session: a #SpiceSession + * + * Disconnect the @session, and destroy all channels. + **/ +void spice_session_disconnect(SpiceSession *session) +{ + SpiceSessionPrivate *s; + + g_return_if_fail(SPICE_IS_SESSION(session)); + + s = session->priv; + + SPICE_DEBUG("session: disconnecting %u", s->disconnecting); + if (s->disconnecting != 0) + return; + + g_object_ref(session); + s->disconnecting = g_idle_add((GSourceFunc)session_disconnect_idle, session); +} + +/** + * spice_session_get_channels: + * @session: a #SpiceSession + * + * Get the list of current channels associated with this @session. + * + * Returns: (element-type SpiceChannel) (transfer container): a #GList + * of unowned #SpiceChannel channels. + **/ +GList *spice_session_get_channels(SpiceSession *session) +{ + SpiceSessionPrivate *s; + struct channel *item; + GList *list = NULL; + RingItem *ring; + + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + g_return_val_if_fail(session->priv != NULL, NULL); + + s = session->priv; + + for (ring = ring_get_head(&s->channels); + ring != NULL; + ring = ring_next(&s->channels, ring)) { + item = SPICE_CONTAINEROF(ring, struct channel, link); + list = g_list_append(list, item->channel); + } + return list; +} + +/** + * spice_session_has_channel_type: + * @session: a #SpiceSession + * @type: a #SpiceChannel:channel-type + * + * See if there is a @type channel in the channels associated with this + * @session. + * + * Returns: TRUE if a @type channel is available otherwise FALSE. + **/ +gboolean spice_session_has_channel_type(SpiceSession *session, gint type) +{ + SpiceSessionPrivate *s; + struct channel *item; + RingItem *ring; + + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + g_return_val_if_fail(session->priv != NULL, FALSE); + + s = session->priv; + + for (ring = ring_get_head(&s->channels); + ring != NULL; + ring = ring_next(&s->channels, ring)) { + item = SPICE_CONTAINEROF(ring, struct channel, link); + if (spice_channel_get_channel_type(item->channel) == type) { + return TRUE; + } + } + return FALSE; +} + +/* ------------------------------------------------------------------ */ +/* private functions */ + +typedef struct spice_open_host spice_open_host; + +struct spice_open_host { + struct coroutine *from; + SpiceSession *session; + SpiceChannel *channel; + SpiceURI *proxy; + int port; + GCancellable *cancellable; + GError *error; + GSocketConnection *connection; + GSocketClient *client; +}; + +static void socket_client_connect_ready(GObject *source_object, GAsyncResult *result, + gpointer data) +{ + GSocketClient *client = G_SOCKET_CLIENT(source_object); + spice_open_host *open_host = data; + GSocketConnection *connection = NULL; + + CHANNEL_DEBUG(open_host->channel, "connect ready"); + connection = g_socket_client_connect_finish(client, result, &open_host->error); + if (connection == NULL) { + g_warn_if_fail(open_host->error != NULL); + goto end; + } + + open_host->connection = connection; + +end: + coroutine_yieldto(open_host->from, NULL); +} + +/* main context */ +static void open_host_connectable_connect(spice_open_host *open_host, GSocketConnectable *connectable) +{ + CHANNEL_DEBUG(open_host->channel, "connecting %p...", open_host); + + g_socket_client_connect_async(open_host->client, connectable, + open_host->cancellable, + socket_client_connect_ready, open_host); +} + +/* main context */ +static void proxy_lookup_ready(GObject *source_object, GAsyncResult *result, + gpointer data) +{ + spice_open_host *open_host = data; + SpiceSession *session = open_host->session; + SpiceSessionPrivate *s = session->priv; + GList *addresses = NULL, *it; + GSocketAddress *address; + + SPICE_DEBUG("proxy lookup ready"); + addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object), + result, &open_host->error); + if (addresses == NULL || open_host->error) { + g_prefix_error(&open_host->error, "SPICE proxy: "); + coroutine_yieldto(open_host->from, NULL); + return; + } + + for (it = addresses; it != NULL; it = it->next) { + address = g_proxy_address_new(G_INET_ADDRESS(it->data), + spice_uri_get_port(open_host->proxy), + spice_uri_get_scheme(open_host->proxy), + s->host, open_host->port, + spice_uri_get_user(open_host->proxy), + spice_uri_get_password(open_host->proxy)); + if (address != NULL) + break; + } + + open_host_connectable_connect(open_host, G_SOCKET_CONNECTABLE(address)); + g_resolver_free_addresses(addresses); + g_object_unref(address); +} + +/* main context */ +static gboolean open_host_idle_cb(gpointer data) +{ + spice_open_host *open_host = data; + SpiceSessionPrivate *s; + + g_return_val_if_fail(open_host != NULL, FALSE); + g_return_val_if_fail(open_host->connection == NULL, FALSE); + + if (spice_channel_get_session(open_host->channel) != open_host->session) + return FALSE; + + s = open_host->session->priv; + open_host->proxy = s->proxy; + if (open_host->error != NULL) { + coroutine_yieldto(open_host->from, NULL); + return FALSE; + } + + if (open_host->proxy) { + g_resolver_lookup_by_name_async(g_resolver_get_default(), + spice_uri_get_hostname(open_host->proxy), + open_host->cancellable, + proxy_lookup_ready, open_host); + } else { + GSocketConnectable *address = NULL; + + if (s->unix_path) { + SPICE_DEBUG("open unix path %s", s->unix_path); +#ifdef G_OS_UNIX + address = G_SOCKET_CONNECTABLE(g_unix_socket_address_new(s->unix_path)); +#else + g_set_error_literal(&open_host->error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Unix path unsupported on this platform"); +#endif + } else { + SPICE_DEBUG("open host %s:%d", s->host, open_host->port); + address = g_network_address_new(s->host, open_host->port); + } + + if (address == NULL || open_host->error != NULL) { + coroutine_yieldto(open_host->from, NULL); + return FALSE; + } + + open_host_connectable_connect(open_host, address); + g_object_unref(address); + } + + if (open_host->proxy != NULL) { + gchar *str = spice_uri_to_string(open_host->proxy); + SPICE_DEBUG("(with proxy %s)", str); + g_free(str); + } + + return FALSE; +} + +#define SOCKET_TIMEOUT 10 + +/* coroutine context */ +G_GNUC_INTERNAL +GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel, + gboolean *use_tls, GError **error) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + SpiceChannelPrivate *c = channel->priv; + spice_open_host open_host = { 0, }; + gchar *port, *endptr; + + // FIXME: make open_host() cancellable + open_host.from = coroutine_self(); + open_host.session = session; + open_host.channel = channel; + + const char *name = spice_channel_type_to_string(c->channel_type); + if (spice_strv_contains(s->secure_channels, "all") || + spice_strv_contains(s->secure_channels, name)) + *use_tls = TRUE; + + if (s->unix_path) { + if (*use_tls) { + CHANNEL_DEBUG(channel, "No TLS for Unix sockets"); + return NULL; + } + } else { + port = *use_tls ? s->tls_port : s->port; + if (port == NULL) { + SPICE_DEBUG("Missing port value, not attempting %s connection.", + *use_tls?"TLS":"unencrypted"); + return NULL; + } + + open_host.port = strtol(port, &endptr, 10); + if (*port == '\0' || *endptr != '\0' || + open_host.port <= 0 || open_host.port > G_MAXUINT16) { + g_warning("Invalid port value %s", port); + return NULL; + } + } + if (*use_tls) { + CHANNEL_DEBUG(channel, "Using TLS, port %d", open_host.port); + } else { + CHANNEL_DEBUG(channel, "Using plain text, port %d", open_host.port); + } + + open_host.client = g_socket_client_new(); + g_socket_client_set_enable_proxy(open_host.client, s->proxy != NULL); + g_socket_client_set_timeout(open_host.client, SOCKET_TIMEOUT); + + g_idle_add(open_host_idle_cb, &open_host); + /* switch to main loop and wait for connection */ + coroutine_yield(NULL); + + if (open_host.error != NULL) { + CHANNEL_DEBUG(channel, "open host: %s", open_host.error->message); + g_propagate_error(error, open_host.error); + } else if (open_host.connection != NULL) { + GSocket *socket; + socket = g_socket_connection_get_socket(open_host.connection); + g_socket_set_timeout(socket, 0); + g_socket_set_blocking(socket, FALSE); + g_socket_set_keepalive(socket, TRUE); + } + + g_clear_object(&open_host.client); + return open_host.connection; +} + + +G_GNUC_INTERNAL +void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + + SpiceSessionPrivate *s = session->priv; + struct channel *item; + + + item = g_new0(struct channel, 1); + item->channel = channel; + ring_add(&s->channels, &item->link); + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + gboolean all = spice_strv_contains(s->disable_effects, "all"); + + g_object_set(channel, + "disable-wallpaper", all || spice_strv_contains(s->disable_effects, "wallpaper"), + "disable-font-smooth", all || spice_strv_contains(s->disable_effects, "font-smooth"), + "disable-animation", all || spice_strv_contains(s->disable_effects, "animation"), + NULL); + if (s->color_depth != 0) + g_object_set(channel, "color-depth", s->color_depth, NULL); + + CHANNEL_DEBUG(channel, "new main channel, switching"); + s->cmain = channel; + } else if (SPICE_IS_PLAYBACK_CHANNEL(channel)) { + g_warn_if_fail(s->playback_channel == NULL); + s->playback_channel = SPICE_PLAYBACK_CHANNEL(channel); + } + + g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_NEW], 0, channel); +} + +static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + + SpiceSessionPrivate *s = session->priv; + struct channel *item = NULL; + RingItem *ring; + + if (s->migration_left) + s->migration_left = g_list_remove(s->migration_left, channel); + + for (ring = ring_get_head(&s->channels); ring != NULL; + ring = ring_next(&s->channels, ring)) { + item = SPICE_CONTAINEROF(ring, struct channel, link); + if (item->channel == channel) + break; + } + + g_return_if_fail(ring != NULL); + + if (channel == s->cmain) { + CHANNEL_DEBUG(channel, "the session lost the main channel"); + s->cmain = NULL; + } + + ring_remove(&item->link); + free(item); + + g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel); + + g_clear_object(&channel->priv->session); + spice_channel_disconnect(channel, SPICE_CHANNEL_NONE); + g_object_unref(channel); +} + +G_GNUC_INTERNAL +void spice_session_set_connection_id(SpiceSession *session, int id) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + s->connection_id = id; +} + +G_GNUC_INTERNAL +int spice_session_get_connection_id(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), -1); + + SpiceSessionPrivate *s = session->priv; + + return s->connection_id; +} + +G_GNUC_INTERNAL +guint32 spice_session_get_mm_time(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), 0); + + SpiceSessionPrivate *s = session->priv; + + /* FIXME: we may want to estimate the drift of clocks, and well, + do something better than this trivial approach */ + return s->mm_time + (g_get_monotonic_time() - s->mm_time_at_clock) / 1000; +} + +#define MM_TIME_DIFF_RESET_THRESH 500 // 0.5 sec + +G_GNUC_INTERNAL +void spice_session_set_mm_time(SpiceSession *session, guint32 time) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + guint32 old_time; + + old_time = spice_session_get_mm_time(session); + + s->mm_time = time; + s->mm_time_at_clock = g_get_monotonic_time(); + SPICE_DEBUG("set mm time: %u", spice_session_get_mm_time(session)); + if (time > old_time + MM_TIME_DIFF_RESET_THRESH || + time < old_time) { + SPICE_DEBUG("%s: mm-time-reset, old %u, new %u", __FUNCTION__, old_time, s->mm_time); + g_coroutine_signal_emit(session, signals[SPICE_SESSION_MM_TIME_RESET], 0); + } +} + +G_GNUC_INTERNAL +void spice_session_set_port(SpiceSession *session, int port, gboolean tls) +{ + const char *prop = tls ? "tls-port" : "port"; + char *tmp; + + g_return_if_fail(SPICE_IS_SESSION(session)); + + /* old spicec client doesn't accept port == 0, see Migrate::start */ + tmp = port > 0 ? g_strdup_printf("%d", port) : NULL; + g_object_set(session, prop, tmp, NULL); + g_free(tmp); +} + +G_GNUC_INTERNAL +void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *size) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + g_return_if_fail(pubkey != NULL); + g_return_if_fail(size != NULL); + + SpiceSessionPrivate *s = session->priv; + + *pubkey = s->pubkey ? s->pubkey->data : NULL; + *size = s->pubkey ? s->pubkey->len : 0; +} + +G_GNUC_INTERNAL +void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + g_return_if_fail(ca != NULL); + g_return_if_fail(size != NULL); + + SpiceSessionPrivate *s = session->priv; + + *ca = s->ca ? s->ca->data : NULL; + *size = s->ca ? s->ca->len : 0; +} + +G_GNUC_INTERNAL +guint spice_session_get_verify(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), 0); + + SpiceSessionPrivate *s = session->priv; + + return s->verify; +} + +G_GNUC_INTERNAL +void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigration state) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + if (state == SPICE_SESSION_MIGRATION_CONNECTING) + s->for_migration = true; + + s->migration_state = state; + g_coroutine_object_notify(G_OBJECT(session), "migration-state"); +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_username(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->username; +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_password(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->password; +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_host(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->host; +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_cert_subject(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->cert_subject; +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_ciphers(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->ciphers; +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_ca_file(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->ca_file; +} + +G_GNUC_INTERNAL +void spice_session_get_caches(SpiceSession *session, + display_cache **images, + SpiceGlzDecoderWindow **glz_window) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + if (images) + *images = s->images; + if (glz_window) + *glz_window = s->glz_window; +} + +G_GNUC_INTERNAL +void spice_session_set_caches_hints(SpiceSession *session, + uint32_t pci_ram_size, + uint32_t n_display_channels) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + s->pci_ram_size = pci_ram_size; + s->n_display_channels = n_display_channels; + + /* TODO: when setting cache and window size, we should consider the client's + * available memory and the number of display channels */ + if (s->images_cache_size == 0) { + s->images_cache_size = IMAGES_CACHE_SIZE_DEFAULT; + } + + if (s->glz_window_size == 0) { + s->glz_window_size = MIN(MAX_GLZ_WINDOW_SIZE_DEFAULT, pci_ram_size / 2); + s->glz_window_size = MAX(MIN_GLZ_WINDOW_SIZE_DEFAULT, s->glz_window_size); + } +} + +G_GNUC_INTERNAL +guint spice_session_get_n_display_channels(SpiceSession *session) +{ + g_return_val_if_fail(session != NULL, 0); + + return session->priv->n_display_channels; +} + +G_GNUC_INTERNAL +void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16]) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + memcpy(s->uuid, uuid, sizeof(s->uuid)); + + g_coroutine_object_notify(G_OBJECT(session), "uuid"); +} + +G_GNUC_INTERNAL +void spice_session_set_name(SpiceSession *session, const gchar *name) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + g_free(s->name); + s->name = g_strdup(name); + + g_coroutine_object_notify(G_OBJECT(session), "name"); +} + +G_GNUC_INTERNAL +void spice_session_sync_playback_latency(SpiceSession *session) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + if (s->playback_channel && + spice_playback_channel_is_active(s->playback_channel)) { + spice_playback_channel_sync_latency(s->playback_channel); + } else { + SPICE_DEBUG("%s: not implemented when there isn't audio playback", __FUNCTION__); + } +} + +G_GNUC_INTERNAL +gboolean spice_session_is_playback_active(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + SpiceSessionPrivate *s = session->priv; + + return (s->playback_channel && + spice_playback_channel_is_active(s->playback_channel)); +} + +G_GNUC_INTERNAL +guint32 spice_session_get_playback_latency(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), 0); + + SpiceSessionPrivate *s = session->priv; + + if (s->playback_channel && + spice_playback_channel_is_active(s->playback_channel)) { + return spice_playback_channel_get_latency(s->playback_channel); + } else { + SPICE_DEBUG("%s: not implemented when there isn't audio playback", __FUNCTION__); + return 0; + } +} + +G_GNUC_INTERNAL +const gchar* spice_session_get_shared_dir(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + SpiceSessionPrivate *s = session->priv; + + return s->shared_dir; +} + +G_GNUC_INTERNAL +void spice_session_set_shared_dir(SpiceSession *session, const gchar *dir) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + + SpiceSessionPrivate *s = session->priv; + + g_free(s->shared_dir); + s->shared_dir = g_strdup(dir); +} + +/** + * spice_session_get_proxy_uri: + * @session: a #SpiceSession + * + * Gets the @session proxy uri. + * + * Returns: (transfer none): the session proxy #SpiceURI or %NULL. + * Since: 0.24 + **/ +SpiceURI *spice_session_get_proxy_uri(SpiceSession *session) +{ + SpiceSessionPrivate *s; + + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + g_return_val_if_fail(session->priv != NULL, NULL); + + s = session->priv; + + return s->proxy; +} + +/** + * spice_audio_get: + * @session: the #SpiceSession to connect to + * @context: (allow-none): a #GMainContext to attach to (or %NULL for default). + * + * Gets the #SpiceAudio associated with the passed in #SpiceSession. + * A new #SpiceAudio instance will be created the first time this + * function is called for a certain #SpiceSession. + * + * Note that this function returns a weak reference, which should not be used + * after the #SpiceSession itself has been unref-ed by the caller. + * + * Returns: (transfer none): a weak reference to a #SpiceAudio + * instance or %NULL if failed. + **/ +SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context) +{ + static GMutex mutex; + SpiceAudio *self; + + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + + g_mutex_lock(&mutex); + self = session->priv->audio_manager; + if (self == NULL) { + self = spice_audio_new(session, context, NULL); + session->priv->audio_manager = self; + } + g_mutex_unlock(&mutex); + + return self; +} + +/** + * spice_usb_device_manager_get: + * @session: #SpiceSession for which to get the #SpiceUsbDeviceManager + * @err: (allow-none): a return location for #GError, or %NULL. + * + * Gets the #SpiceUsbDeviceManager associated with the passed in #SpiceSession. + * A new #SpiceUsbDeviceManager instance will be created the first time this + * function is called for a certain #SpiceSession. + * + * Note that this function returns a weak reference, which should not be used + * after the #SpiceSession itself has been unref-ed by the caller. + * + * Returns: (transfer none): a weak reference to the #SpiceUsbDeviceManager associated with the passed in #SpiceSession + */ +SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session, + GError **err) +{ + SpiceUsbDeviceManager *self; + static GMutex mutex; + + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + g_return_val_if_fail(err == NULL || *err == NULL, NULL); + + g_mutex_lock(&mutex); + self = session->priv->usb_manager; + if (self == NULL) { + self = g_initable_new(SPICE_TYPE_USB_DEVICE_MANAGER, NULL, err, + "session", session, NULL); + session->priv->usb_manager = self; + } + g_mutex_unlock(&mutex); + + return self; +} + +G_GNUC_INTERNAL +gboolean spice_session_get_audio_enabled(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + return session->priv->audio; +} + +G_GNUC_INTERNAL +gboolean spice_session_get_usbredir_enabled(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + return session->priv->usbredir; +} + +G_GNUC_INTERNAL +gboolean spice_session_get_smartcard_enabled(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + return session->priv->smartcard; +} + +G_GNUC_INTERNAL +PhodavServer* spice_session_get_webdav_server(SpiceSession *session) +{ + SpiceSessionPrivate *priv; + + g_return_val_if_fail(SPICE_IS_SESSION(session), NULL); + priv = session->priv; + +#ifdef USE_PHODAV + static GMutex mutex; + + const gchar *shared_dir = spice_session_get_shared_dir(session); + if (shared_dir == NULL) { + SPICE_DEBUG("No shared dir set, not creating webdav server"); + return NULL; + } + + g_mutex_lock(&mutex); + + if (priv->webdav) + goto end; + + priv->webdav = phodav_server_new(shared_dir); + g_object_bind_property(session, "share-dir-ro", + priv->webdav, "read-only", + G_BINDING_SYNC_CREATE|G_BINDING_BIDIRECTIONAL); + g_object_bind_property(session, "shared-dir", + priv->webdav, "root", + G_BINDING_SYNC_CREATE|G_BINDING_BIDIRECTIONAL); + +end: + g_mutex_unlock(&mutex); +#endif + + return priv->webdav; +} + +/** + * spice_session_is_for_migration: + * @session: a Spice session + * + * During seamless migration, channels may be created to establish a + * connection with the target, but they are temporary and should only + * handle migration steps. In order to avoid other interactions with + * the client, channels should check this value. + * + * Returns: %TRUE if the session is a copy created during migration + * Since: 0.27 + **/ +gboolean spice_session_is_for_migration(SpiceSession *session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + + return session->priv->for_migration; +} + +G_GNUC_INTERNAL +void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel) +{ + g_return_if_fail(SPICE_IS_SESSION(session)); + g_return_if_fail(SPICE_IS_CHANNEL(channel)); + g_return_if_fail(session->priv->cmain == NULL); + + session->priv->cmain = channel; +} + +G_GNUC_INTERNAL +gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session) +{ + g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE); + g_return_val_if_fail(SPICE_IS_SESSION(mig_session), FALSE); + g_return_val_if_fail(session->priv->migration == NULL, FALSE); + + session->priv->migration = mig_session; + + return TRUE; +} diff --git a/src/spice-session.h b/src/spice-session.h new file mode 100644 index 0000000..cfe02b1 --- /dev/null +++ b/src/spice-session.h @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_SESSION_H__ +#define __SPICE_CLIENT_SESSION_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include +#include "spice-types.h" +#include "spice-uri.h" +#include "spice-glib-enums.h" +#include "spice-util.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_SESSION (spice_session_get_type ()) +#define SPICE_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_SESSION, SpiceSession)) +#define SPICE_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_SESSION, SpiceSessionClass)) +#define SPICE_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_SESSION)) +#define SPICE_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_SESSION)) +#define SPICE_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_SESSION, SpiceSessionClass)) + +/** + * SpiceSessionVerify: + * @SPICE_SESSION_VERIFY_PUBKEY: verify certificate public key matching + * @SPICE_SESSION_VERIFY_HOSTNAME: verify certificate hostname matching + * @SPICE_SESSION_VERIFY_SUBJECT: verify certificate subject matching + * + * Peer certificate verification parameters flags. + **/ +typedef enum { + SPICE_SESSION_VERIFY_PUBKEY = (1 << 0), + SPICE_SESSION_VERIFY_HOSTNAME = (1 << 1), + SPICE_SESSION_VERIFY_SUBJECT = (1 << 2), +} SpiceSessionVerify; + +/** + * SpiceSessionMigration: + * @SPICE_SESSION_MIGRATION_NONE: no migration going on + * @SPICE_SESSION_MIGRATION_SWITCHING: the session is switching host (destroy and reconnect) + * @SPICE_SESSION_MIGRATION_MIGRATING: the session is migrating seamlessly (reconnect) + * @SPICE_SESSION_MIGRATION_CONNECTING: the migration is connecting to destination (Since: 0.27) + * + * Session migration state. + **/ +typedef enum { + SPICE_SESSION_MIGRATION_NONE, + SPICE_SESSION_MIGRATION_SWITCHING, + SPICE_SESSION_MIGRATION_MIGRATING, + SPICE_SESSION_MIGRATION_CONNECTING, +} SpiceSessionMigration; + +/** + * SpiceSession: + * + * The #SpiceSession struct is opaque and should not be accessed directly. + */ +struct _SpiceSession +{ + GObject parent; + SpiceSessionPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceSessionClass: + * @parent_class: Parent class. + * @channel_new: Signal class handler for the #SpiceSession::channel_new signal. + * @channel_destroy: Signal class handler for the #SpiceSession::channel_destroy signal. + * + * Class structure for #SpiceSession. + */ +struct _SpiceSessionClass +{ + GObjectClass parent_class; + + /* signals */ + void (*channel_new)(SpiceSession *session, SpiceChannel *channel); + void (*channel_destroy)(SpiceSession *session, SpiceChannel *channel); + + /*< private >*/ + /* + * If adding fields to this struct, remove corresponding + * amount of padding to avoid changing overall struct size + */ + gchar _spice_reserved[SPICE_RESERVED_PADDING]; +}; + +GType spice_session_get_type(void); + +SpiceSession *spice_session_new(void); +gboolean spice_session_connect(SpiceSession *session); +gboolean spice_session_open_fd(SpiceSession *session, int fd); +void spice_session_disconnect(SpiceSession *session); +GList *spice_session_get_channels(SpiceSession *session); +gboolean spice_session_has_channel_type(SpiceSession *session, gint type); +gboolean spice_session_get_read_only(SpiceSession *session); +SpiceURI *spice_session_get_proxy_uri(SpiceSession *session); +gboolean spice_session_is_for_migration(SpiceSession *session); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_SESSION_H__ */ diff --git a/src/spice-types.h b/src/spice-types.h new file mode 100644 index 0000000..ccc0c3a --- /dev/null +++ b/src/spice-types.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_TYPES_H__ +#define __SPICE_CLIENT_TYPES_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +G_BEGIN_DECLS + +/* SpiceSession */ +typedef struct _SpiceSession SpiceSession; +typedef struct _SpiceSessionClass SpiceSessionClass; +typedef struct _SpiceSessionPrivate SpiceSessionPrivate; + +/* SpiceChannel */ +typedef struct _SpiceChannel SpiceChannel; +typedef struct _SpiceChannelClass SpiceChannelClass; +typedef struct _SpiceChannelPrivate SpiceChannelPrivate; + +G_END_DECLS + +#endif /* __SPICE_CLIENT_TYPES_H__ */ diff --git a/src/spice-uri-priv.h b/src/spice-uri-priv.h new file mode 100644 index 0000000..54351de --- /dev/null +++ b/src/spice-uri-priv.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_URI_PRIV_H__ +#define __SPICE_URI_PRIV_H__ + +#include "spice-uri.h" + +G_BEGIN_DECLS + +SpiceURI* spice_uri_new(void); +gboolean spice_uri_parse(SpiceURI* self, const gchar* uri, GError** error); + +G_END_DECLS + +#endif /* __SPICE_URI_PRIV_H__ */ diff --git a/src/spice-uri.c b/src/spice-uri.c new file mode 100644 index 0000000..0376cd8 --- /dev/null +++ b/src/spice-uri.c @@ -0,0 +1,529 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#include "spice-client.h" +#include "spice-uri.h" +#include "spice-uri-priv.h" + +/** + * SECTION:spice-uri + * @short_description: URIs handling + * @title: SpiceURI + * @section_id: + * @stability: Stable + * @include: spice-client.h + * + * A SpiceURI represents a (parsed) URI. + * Since: 0.24 + */ + +struct _SpiceURI { + GObject parent_instance; + gchar *scheme; + gchar *hostname; + guint port; + gchar *user; + gchar *password; +}; + +struct _SpiceURIClass { + GObjectClass parent_class; +}; + +G_DEFINE_TYPE(SpiceURI, spice_uri, G_TYPE_OBJECT); + +enum { + SPICE_URI_DUMMY_PROPERTY, + SPICE_URI_SCHEME, + SPICE_URI_USER, + SPICE_URI_PASSWORD, + SPICE_URI_HOSTNAME, + SPICE_URI_PORT +}; + +#ifndef HAVE_STRTOK_R +static char *strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) + s = *save_ptr; + + /* Scan leading delimiters. */ + s += strspn (s, delim); + if (*s == '\0') + return NULL; + + /* Find the end of the token. */ + token = s; + s = strpbrk (token, delim); + if (s == NULL) + /* This token finishes the string. */ + *save_ptr = strchr (token, '\0'); + else + { + /* Terminate the token and make *SAVE_PTR point past it. */ + *s = '\0'; + *save_ptr = s + 1; + } + return token; +} +#endif + +G_GNUC_INTERNAL +SpiceURI* spice_uri_new(void) +{ + SpiceURI * self = NULL; + self = (SpiceURI*)g_object_new(SPICE_TYPE_URI, NULL); + return self; +} + +static void spice_uri_reset(SpiceURI *self) +{ + g_clear_pointer(&self->scheme, g_free); + g_clear_pointer(&self->hostname, g_free); + g_clear_pointer(&self->user, g_free); + g_clear_pointer(&self->password, g_free); + self->port = 0; +} + +G_GNUC_INTERNAL +gboolean spice_uri_parse(SpiceURI *self, const gchar *_uri, GError **error) +{ + gchar *dup, *uri, **uriv = NULL; + const gchar *uri_port = NULL; + char *uri_scheme = NULL; + gboolean success = FALSE; + size_t len; + + g_return_val_if_fail(self != NULL, FALSE); + + spice_uri_reset(self); + + g_return_val_if_fail(_uri != NULL, FALSE); + + uri = dup = g_strdup(_uri); + /* FIXME: use GUri when it is ready... only support http atm */ + /* the code is voluntarily not parsing thoroughly the uri */ + uri_scheme = g_uri_parse_scheme(uri); + if (uri_scheme == NULL) { + spice_uri_set_scheme(self, "http"); + } else { + spice_uri_set_scheme(self, uri_scheme); + uri += strlen(uri_scheme) + 3; /* scheme + "://" */ + } + if (g_ascii_strcasecmp(spice_uri_get_scheme(self), "http") == 0) { + spice_uri_set_port(self, 3128); + } else if (g_ascii_strcasecmp(spice_uri_get_scheme(self), "https") == 0) { + spice_uri_set_port(self, 3129); + } else { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid uri scheme for proxy: %s", spice_uri_get_scheme(self)); + goto end; + } + /* remove trailing slash */ + len = strlen(uri); + for (; len > 0; len--) + if (uri[len-1] == '/') + uri[len-1] = '\0'; + else + break; + + + /* yes, that parser is bad, we need GUri... */ + if (strstr(uri, "@")) { + gchar *saveptr = NULL, *saveptr2 = NULL; + gchar *next = strstr(uri, "@") + 1; + gchar *auth = strtok_r(uri, "@", &saveptr); + const gchar *user = strtok_r(auth, ":", &saveptr2); + const gchar *pass = strtok_r(NULL, ":", &saveptr2); + spice_uri_set_user(self, user); + spice_uri_set_password(self, pass); + uri = next; + } + + if (*uri == '[') { /* ipv6 address */ + uriv = g_strsplit(uri + 1, "]", 2); + if (uriv[1] == NULL) { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Missing ']' in ipv6 uri"); + goto end; + } + if (*uriv[1] == ':') { + uri_port = uriv[1] + 1; + } else if (strlen(uriv[1]) > 0) { /* invalid string after the hostname */ + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid uri address"); + goto end; + } + } else { + /* max 2 parts, host:port */ + uriv = g_strsplit(uri, ":", 2); + if (uriv[0] != NULL) + uri_port = uriv[1]; + } + + if (uriv[0] == NULL || strlen(uriv[0]) == 0) { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid hostname in uri address"); + goto end; + } + + spice_uri_set_hostname(self, uriv[0]); + + if (uri_port != NULL) { + gchar *endptr; + gint64 port = g_ascii_strtoll(uri_port, &endptr, 10); + if (*endptr != '\0') { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Invalid uri port: %s", uri_port); + goto end; + } else if (endptr == uri_port) { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, "Missing uri port"); + goto end; + } + if (port <= 0 || port > 65535) { + g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, "Port out of range"); + goto end; + } + spice_uri_set_port(self, port); + } + + success = TRUE; + +end: + free(uri_scheme); + g_free(dup); + g_strfreev(uriv); + return success; +} + +/** + * spice_uri_get_scheme: + * @uri: a #SpiceURI + * + * Gets @uri's scheme. + * + * Returns: @uri's scheme. + * Since: 0.24 + **/ +const gchar* spice_uri_get_scheme(SpiceURI *self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), NULL); + return self->scheme; +} + +/** + * spice_uri_set_scheme: + * @uri: a #SpiceURI + * @scheme: the scheme + * + * Sets @uri's scheme to @scheme. + * Since: 0.24 + **/ +void spice_uri_set_scheme(SpiceURI *self, const gchar *scheme) +{ + g_return_if_fail(SPICE_IS_URI(self)); + + g_free(self->scheme); + self->scheme = g_strdup(scheme); + g_object_notify((GObject *)self, "scheme"); +} + +/** + * spice_uri_get_hostname: + * @uri: a #SpiceURI + * + * Gets @uri's hostname. + * + * Returns: @uri's hostname. + * Since: 0.24 + **/ +const gchar* spice_uri_get_hostname(SpiceURI *self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), NULL); + return self->hostname; +} + + +/** + * spice_uri_set_hostname: + * @uri: a #SpiceURI + * @hostname: the hostname + * + * Sets @uri's hostname to @hostname. + * Since: 0.24 + **/ +void spice_uri_set_hostname(SpiceURI *self, const gchar *hostname) +{ + g_return_if_fail(SPICE_IS_URI(self)); + + g_free(self->hostname); + self->hostname = g_strdup(hostname); + g_object_notify((GObject *)self, "hostname"); +} + +/** + * spice_uri_get_port: + * @uri: a #SpiceURI + * + * Gets @uri's port. + * + * Returns: @uri's port. + * Since: 0.24 + **/ +guint spice_uri_get_port(SpiceURI *self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), 0); + return self->port; +} + +/** + * spice_uri_set_port: + * @uri: a #SpiceURI + * @port: the port + * + * Sets @uri's port to @port. + * Since: 0.24 + **/ +void spice_uri_set_port(SpiceURI *self, guint port) +{ + g_return_if_fail(SPICE_IS_URI(self)); + self->port = port; + g_object_notify((GObject *)self, "port"); +} + +static void spice_uri_get_property(GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + SpiceURI *self; + self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_URI, SpiceURI); + + switch (property_id) { + case SPICE_URI_SCHEME: + g_value_set_string(value, spice_uri_get_scheme(self)); + break; + case SPICE_URI_HOSTNAME: + g_value_set_string(value, spice_uri_get_hostname(self)); + break; + case SPICE_URI_PORT: + g_value_set_uint(value, spice_uri_get_port(self)); + break; + case SPICE_URI_USER: + g_value_set_string(value, spice_uri_get_user(self)); + break; + case SPICE_URI_PASSWORD: + g_value_set_string(value, spice_uri_get_password(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + + +static void spice_uri_set_property(GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + SpiceURI * self; + self = G_TYPE_CHECK_INSTANCE_CAST(object, SPICE_TYPE_URI, SpiceURI); + + switch (property_id) { + case SPICE_URI_SCHEME: + spice_uri_set_scheme(self, g_value_get_string(value)); + break; + case SPICE_URI_HOSTNAME: + spice_uri_set_hostname(self, g_value_get_string(value)); + break; + case SPICE_URI_USER: + spice_uri_set_user(self, g_value_get_string(value)); + break; + case SPICE_URI_PASSWORD: + spice_uri_set_password(self, g_value_get_string(value)); + break; + case SPICE_URI_PORT: + spice_uri_set_port(self, g_value_get_uint(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void spice_uri_finalize(GObject* obj) +{ + SpiceURI *self; + + self = G_TYPE_CHECK_INSTANCE_CAST(obj, SPICE_TYPE_URI, SpiceURI); + spice_uri_reset(self); + + G_OBJECT_CLASS (spice_uri_parent_class)->finalize (obj); +} + +static void spice_uri_init (SpiceURI *self G_GNUC_UNUSED) +{ +} + + +static void spice_uri_class_init(SpiceURIClass *klass) +{ + spice_uri_parent_class = g_type_class_peek_parent (klass); + + G_OBJECT_CLASS (klass)->get_property = spice_uri_get_property; + G_OBJECT_CLASS (klass)->set_property = spice_uri_set_property; + G_OBJECT_CLASS (klass)->finalize = spice_uri_finalize; + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_URI_SCHEME, + g_param_spec_string ("scheme", + "scheme", + "scheme", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_URI_HOSTNAME, + g_param_spec_string ("hostname", + "hostname", + "hostname", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_URI_PORT, + g_param_spec_uint ("port", + "port", + "port", + 0, G_MAXUINT, 0, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_URI_USER, + g_param_spec_string ("user", + "user", + "user", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS (klass), + SPICE_URI_PASSWORD, + g_param_spec_string ("password", + "password", + "password", + NULL, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE)); +} + +/** + * spice_uri_to_string: + * @uri: a #SpiceURI + * + * Returns a string representing @uri. + * + * Returns: a string representing @uri, which the caller must free. + * Since: 0.24 + **/ +gchar* spice_uri_to_string(SpiceURI* self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), NULL); + + if (self->scheme == NULL || self->hostname == NULL) + return NULL; + + if (self->user || self->password) + return g_strdup_printf("%s://%s:%s@%s:%u", + self->scheme, + self->user, self->password, + self->hostname, self->port); + else + return g_strdup_printf("%s://%s:%u", + self->scheme, self->hostname, self->port); +} + +/** + * spice_uri_get_user: + * @uri: a #SpiceURI + * + * Gets @uri's user. + * + * Returns: @uri's user. + * Since: 0.24 + **/ +const gchar* spice_uri_get_user(SpiceURI *self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), NULL); + return self->user; +} + +/** + * spice_uri_set_user: + * @uri: a #SpiceURI + * @user: the user, or %NULL. + * + * Sets @uri's user to @user. + * Since: 0.24 + **/ +void spice_uri_set_user(SpiceURI *self, const gchar *user) +{ + g_return_if_fail(SPICE_IS_URI(self)); + + g_free(self->user); + self->user = g_strdup(user); + g_object_notify((GObject *)self, "user"); +} + +/** + * spice_uri_get_password: + * @uri: a #SpiceURI + * + * Gets @uri's password. + * + * Returns: @uri's password. + * Since: 0.24 + **/ +const gchar* spice_uri_get_password(SpiceURI *self) +{ + g_return_val_if_fail(SPICE_IS_URI(self), NULL); + return self->password; +} + +/** + * spice_uri_set_password: + * @uri: a #SpiceURI + * @password: the password, or %NULL. + * + * Sets @uri's password to @password. + * Since: 0.24 + **/ +void spice_uri_set_password(SpiceURI *self, const gchar *password) +{ + g_return_if_fail(SPICE_IS_URI(self)); + + g_free(self->password); + self->password = g_strdup(password); + g_object_notify((GObject *)self, "password"); +} diff --git a/src/spice-uri.h b/src/spice-uri.h new file mode 100644 index 0000000..9960712 --- /dev/null +++ b/src/spice-uri.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_URI_H__ +#define __SPICE_URI_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include + +G_BEGIN_DECLS + +#define SPICE_TYPE_URI (spice_uri_get_type ()) +#define SPICE_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_URI, SpiceURI)) +#define SPICE_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_URI, SpiceURIClass)) +#define SPICE_IS_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_URI)) +#define SPICE_IS_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_URI)) +#define SPICE_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_URI, SpiceURIClass)) + +/** + * SpiceURI: + * + * The #SpiceURI struct is opaque and cannot be accessed directly. + */ +typedef struct _SpiceURI SpiceURI; + +/** + * SpiceURIClass: + * + * The #SpiceURIClass struct is opaque and cannot be accessed directly. + * It is class structure for #SpiceURI. + */ +typedef struct _SpiceURIClass SpiceURIClass; +typedef struct _SpiceURIPrivate SpiceURIPrivate; + +GType spice_uri_get_type(void) G_GNUC_CONST; + +const gchar* spice_uri_get_scheme(SpiceURI* uri); +void spice_uri_set_scheme(SpiceURI* uri, const gchar* scheme); +const gchar* spice_uri_get_hostname(SpiceURI* uri); +void spice_uri_set_hostname(SpiceURI* uri, const gchar* hostname); +guint spice_uri_get_port(SpiceURI* uri); +void spice_uri_set_port(SpiceURI* uri, guint port); +gchar *spice_uri_to_string(SpiceURI* uri); +const gchar* spice_uri_get_user(SpiceURI* uri); +void spice_uri_set_user(SpiceURI* uri, const gchar* user); +const gchar* spice_uri_get_password(SpiceURI* uri); +void spice_uri_set_password(SpiceURI* uri, const gchar* password); + +G_END_DECLS + +#endif /* __SPICE_URI_H__ */ diff --git a/src/spice-util-priv.h b/src/spice-util-priv.h new file mode 100644 index 0000000..d5e1b8a --- /dev/null +++ b/src/spice-util-priv.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICE_UTIL_PRIV_H +#define SPICE_UTIL_PRIV_H + +#include +#include "spice-util.h" + +G_BEGIN_DECLS + +#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + +gboolean spice_strv_contains(const GStrv strv, const gchar *str); +const gchar* spice_yes_no(gboolean value); +guint16 spice_make_scancode(guint scancode, gboolean release); +gchar* spice_unix2dos(const gchar *str, gssize len, GError **error); +gchar* spice_dos2unix(const gchar *str, gssize len, GError **error); +void spice_mono_edge_highlight(unsigned width, unsigned hight, + const guint8 *and, const guint8 *xor, guint8 *dest); + +G_END_DECLS + +#endif /* SPICE_UTIL_PRIV_H */ diff --git a/src/spice-util.c b/src/spice-util.c new file mode 100644 index 0000000..7788921 --- /dev/null +++ b/src/spice-util.c @@ -0,0 +1,497 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + Copyright © 2006-2010 Collabora Ltd. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include +#include +#include +#include +#include "spice-util-priv.h" +#include "spice-util.h" +#include "spice-util-priv.h" + +/** + * SECTION:spice-util + * @short_description: version and debugging functions + * @title: Utilities + * @section_id: + * @stability: Stable + * @include: spice-client.h + * + * Various functions for debugging and informational purposes. + */ + +static GOnce debug_once = G_ONCE_INIT; + +static void spice_util_enable_debug_messages(void) +{ + const gchar *doms = g_getenv("G_MESSAGES_DEBUG"); + if (!doms) { + g_setenv("G_MESSAGES_DEBUG", G_LOG_DOMAIN, 1); + } else if (g_str_equal(doms, "all")) { + return; + } else if (!strstr(doms, G_LOG_DOMAIN)) { + gchar *newdoms = g_strdup_printf("%s %s", doms, G_LOG_DOMAIN); + g_setenv("G_MESSAGES_DEBUG", newdoms, 1); + g_free(newdoms); + } +} + +/** + * spice_util_set_debug: + * @enabled: %TRUE or %FALSE + * + * Enable or disable Spice-GTK debugging messages. + **/ +void spice_util_set_debug(gboolean enabled) +{ + /* Make sure debug_once has been initialised + * with the value of SPICE_DEBUG already, otherwise + * spice_util_get_debug() may overwrite the value + * that was just set using spice_util_set_debug() + */ + spice_util_get_debug(); + + if (enabled) { + spice_util_enable_debug_messages(); + } + + debug_once.retval = GINT_TO_POINTER(enabled); +} + +static gpointer getenv_debug(gpointer data) +{ + gboolean debug; + + debug = (g_getenv("SPICE_DEBUG") != NULL); + if (debug) + spice_util_enable_debug_messages(); + + return GINT_TO_POINTER(debug); +} + +gboolean spice_util_get_debug(void) +{ + g_once(&debug_once, getenv_debug, NULL); + + return GPOINTER_TO_INT(debug_once.retval); +} + +/** + * spice_util_get_version_string: + * + * Gets the version string + * + * Returns: Spice-GTK version as a const string. + **/ +const gchar *spice_util_get_version_string(void) +{ + return VERSION; +} + +G_GNUC_INTERNAL +gboolean spice_strv_contains(const GStrv strv, const gchar *str) +{ + int i; + + if (strv == NULL) + return FALSE; + + for (i = 0; strv[i] != NULL; i++) + if (g_str_equal(strv[i], str)) + return TRUE; + + return FALSE; +} + +/** + * spice_uuid_to_string: + * @uuid: UUID byte array + * + * Creates a string representation of @uuid, of the form + * "06e023d5-86d8-420e-8103-383e4566087a" + * + * Returns: A string that should be freed with g_free(). + * Since: 0.22 + **/ +gchar* spice_uuid_to_string(const guint8 uuid[16]) +{ + return g_strdup_printf(UUID_FMT, uuid[0], uuid[1], + uuid[2], uuid[3], uuid[4], uuid[5], + uuid[6], uuid[7], uuid[8], uuid[9], + uuid[10], uuid[11], uuid[12], uuid[13], + uuid[14], uuid[15]); +} + +typedef struct { + GObject *instance; + GObject *observer; + GClosure *closure; + gulong handler_id; +} WeakHandlerCtx; + +static WeakHandlerCtx * +whc_new (GObject *instance, + GObject *observer) +{ + WeakHandlerCtx *ctx = g_new0 (WeakHandlerCtx, 1); + + ctx->instance = instance; + ctx->observer = observer; + + return ctx; +} + +static void +whc_free (WeakHandlerCtx *ctx) +{ + g_free (ctx); +} + +static void observer_destroyed_cb (gpointer, GObject *); +static void closure_invalidated_cb (gpointer, GClosure *); + +/* + * If signal handlers are removed before the object is destroyed, this + * callback will never get triggered. + */ +static void +instance_destroyed_cb (gpointer ctx_, + GObject *where_the_instance_was) +{ + WeakHandlerCtx *ctx = ctx_; + + /* No need to disconnect the signal here, the instance has gone away. */ + g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); + g_closure_remove_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + whc_free (ctx); +} + +/* Triggered when the observer is destroyed. */ +static void +observer_destroyed_cb (gpointer ctx_, + GObject *where_the_observer_was) +{ + WeakHandlerCtx *ctx = ctx_; + + g_closure_remove_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + g_signal_handler_disconnect (ctx->instance, ctx->handler_id); + g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); + whc_free (ctx); +} + +/* Triggered when either object is destroyed or the handler is disconnected. */ +static void +closure_invalidated_cb (gpointer ctx_, + GClosure *where_the_closure_was) +{ + WeakHandlerCtx *ctx = ctx_; + + g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); + g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx); + whc_free (ctx); +} + +/* Copied from tp_g_signal_connect_object. See documentation. */ +/** + * spice_g_signal_connect_object: (skip) + * @instance: the instance to connect to. + * @detailed_signal: a string of the form "signal-name::detail". + * @c_handler: the #GCallback to connect. + * @gobject: the object to pass as data to @c_handler. + * @connect_flags: a combination of #GConnectFlags. + * + * Similar to g_signal_connect_object() but will delete connection + * when any of the objects is destroyed. + * + * Returns: the handler id. + */ +gulong spice_g_signal_connect_object (gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer gobject, + GConnectFlags connect_flags) +{ + GObject *instance_obj = G_OBJECT (instance); + WeakHandlerCtx *ctx = whc_new (instance_obj, gobject); + + g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); + g_return_val_if_fail (detailed_signal != NULL, 0); + g_return_val_if_fail (c_handler != NULL, 0); + g_return_val_if_fail (G_IS_OBJECT (gobject), 0); + g_return_val_if_fail ( + (connect_flags & ~(G_CONNECT_AFTER|G_CONNECT_SWAPPED)) == 0, 0); + + if (connect_flags & G_CONNECT_SWAPPED) + ctx->closure = g_cclosure_new_object_swap (c_handler, gobject); + else + ctx->closure = g_cclosure_new_object (c_handler, gobject); + + ctx->handler_id = g_signal_connect_closure (instance, detailed_signal, + ctx->closure, (connect_flags & G_CONNECT_AFTER) ? TRUE : FALSE); + + g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx); + g_object_weak_ref (gobject, observer_destroyed_cb, ctx); + g_closure_add_invalidate_notifier (ctx->closure, ctx, + closure_invalidated_cb); + + return ctx->handler_id; +} + +G_GNUC_INTERNAL +const gchar* spice_yes_no(gboolean value) +{ + return value ? "yes" : "no"; +} + +G_GNUC_INTERNAL +guint16 spice_make_scancode(guint scancode, gboolean release) +{ + SPICE_DEBUG("%s: %s scancode %u", + __FUNCTION__, release ? "release" : "", scancode); + + if (release) { + if (scancode < 0x100) + return scancode | 0x80; + else + return 0x80e0 | ((scancode - 0x100) << 8); + } else { + if (scancode < 0x100) + return scancode; + else + return 0xe0 | ((scancode - 0x100) << 8); + } + + g_return_val_if_reached(0); +} + +typedef enum { + NEWLINE_TYPE_LF, + NEWLINE_TYPE_CR_LF +} NewlineType; + +static gssize get_line(const gchar *str, gsize len, + NewlineType type, gsize *nl_len, + GError **error) +{ + const gchar *p, *endl; + gsize nl = 0; + + endl = (type == NEWLINE_TYPE_CR_LF) ? "\r\n" : "\n"; + p = g_strstr_len(str, len, endl); + if (p) { + len = p - str; + nl = strlen(endl); + } + + *nl_len = nl; + return len; +} + + +static gchar* spice_convert_newlines(const gchar *str, gssize len, + NewlineType from, + NewlineType to, + GError **error) +{ + GError *err = NULL; + gssize length; + gsize nl; + GString *output; + gboolean free_segment = FALSE; + gint i; + + g_return_val_if_fail(str != NULL, NULL); + g_return_val_if_fail(len >= -1, NULL); + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + /* only 2 supported combinations */ + g_return_val_if_fail((from == NEWLINE_TYPE_LF && + to == NEWLINE_TYPE_CR_LF) || + (from == NEWLINE_TYPE_CR_LF && + to == NEWLINE_TYPE_LF), NULL); + + if (len == -1) + len = strlen(str); + /* sometime we get \0 terminated strings, skip that, or it fails + to utf8 validate line with \0 end */ + else if (len > 0 && str[len-1] == 0) + len -= 1; + + /* allocate worst case, if it's small enough, we don't care much, + * if it's big, malloc will put us in mmap'd region, and we can + * over allocate. + */ + output = g_string_sized_new(len * 2 + 1); + + for (i = 0; i < len; i += length + nl) { + length = get_line(str + i, len - i, from, &nl, &err); + if (length < 0) + break; + + g_string_append_len(output, str + i, length); + + if (nl) { + /* let's not double \r if it's already in the line */ + if (to == NEWLINE_TYPE_CR_LF && + output->str[output->len - 1] != '\r') + g_string_append_c(output, '\r'); + + g_string_append_c(output, '\n'); + } + } + + if (err) { + g_propagate_error(error, err); + free_segment = TRUE; + } + + return g_string_free(output, free_segment); +} + +G_GNUC_INTERNAL +gchar* spice_dos2unix(const gchar *str, gssize len, GError **error) +{ + return spice_convert_newlines(str, len, + NEWLINE_TYPE_CR_LF, + NEWLINE_TYPE_LF, + error); +} + +G_GNUC_INTERNAL +gchar* spice_unix2dos(const gchar *str, gssize len, GError **error) +{ + return spice_convert_newlines(str, len, + NEWLINE_TYPE_LF, + NEWLINE_TYPE_CR_LF, + error); +} + +static bool buf_is_ones(unsigned size, const guint8 *data) +{ + int i; + + for (i = 0 ; i < size; ++i) { + if (data[i] != 0xff) { + return false; + } + } + return true; +} + +static bool is_edge_helper(const guint8 *xor, int bpl, int x, int y) +{ + return (xor[bpl * y + (x / 8)] & (0x80 >> (x % 8))) > 0; +} + +static bool is_edge(unsigned width, unsigned height, const guint8 *xor, int bpl, int x, int y) +{ + if (x == 0 || x == width -1 || y == 0 || y == height - 1) { + return 0; + } +#define P(x, y) is_edge_helper(xor, bpl, x, y) + return !P(x, y) && (P(x - 1, y + 1) || P(x, y + 1) || P(x + 1, y + 1) || + P(x - 1, y) || P(x + 1, y) || + P(x - 1, y - 1) || P(x, y - 1) || P(x + 1, y - 1)); +#undef P +} + +/* Mono cursors have two places, "and" and "xor". If a bit is 1 in both, it + * means invertion of the corresponding pixel in the display. Since X11 (and + * gdk) doesn't do invertion, instead we do edge detection and turn the + * sorrounding edge pixels black, and the invert-me pixels white. To + * illustrate: + * + * and xor dest RGB (1=0xffffff, 0=0x000000) + * + * dest alpha (1=0xff, 0=0x00) + * + * 11111 00000 00000 00000 + * 11111 00000 00000 01110 + * 11111 00100 => 00100 01110 + * 11111 00100 00100 01110 + * 11111 00000 00000 01110 + * 11111 00000 00000 00000 + * + * See tests/util.c for more tests + * + * Notes: + * Assumes width >= 8 (i.e. bytes per line is at least 1) + * Assumes edges are not on the boundary (first/last line/column) for simplicity + * + */ +G_GNUC_INTERNAL +void spice_mono_edge_highlight(unsigned width, unsigned height, + const guint8 *and, const guint8 *xor, guint8 *dest) +{ + int bpl = (width + 7) / 8; + bool and_ones = buf_is_ones(height * bpl, and); + int x, y, bit; + const guint8 *xor_base = xor; + + for (y = 0; y < height; y++) { + bit = 0x80; + for (x = 0; x < width; x++, dest += 4) { + if (is_edge(width, height, xor_base, bpl, x, y) && and_ones) { + dest[0] = 0x00; + dest[1] = 0x00; + dest[2] = 0x00; + dest[3] = 0xff; + goto next_bit; + } + if (and[x/8] & bit) { + if (xor[x/8] & bit) { + dest[0] = 0xff; + dest[1] = 0xff; + dest[2] = 0xff; + dest[3] = 0xff; + } else { + /* unchanged -> transparent */ + dest[0] = 0x00; + dest[1] = 0x00; + dest[2] = 0x00; + dest[3] = 0x00; + } + } else { + if (xor[x/8] & bit) { + /* set -> white */ + dest[0] = 0xff; + dest[1] = 0xff; + dest[2] = 0xff; + dest[3] = 0xff; + } else { + /* clear -> black */ + dest[0] = 0x00; + dest[1] = 0x00; + dest[2] = 0x00; + dest[3] = 0xff; + } + } + next_bit: + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + and += bpl; + xor += bpl; + } +} diff --git a/src/spice-util.h b/src/spice-util.h new file mode 100644 index 0000000..88e3a57 --- /dev/null +++ b/src/spice-util.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef SPICE_UTIL_H +#define SPICE_UTIL_H + +#include + +G_BEGIN_DECLS + +void spice_util_set_debug(gboolean enabled); +gboolean spice_util_get_debug(void); +const gchar *spice_util_get_version_string(void); +gulong spice_g_signal_connect_object(gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + gpointer gobject, + GConnectFlags connect_flags); +gchar* spice_uuid_to_string(const guint8 uuid[16]); + +#define SPICE_DEBUG(fmt, ...) \ + do { \ + if (G_UNLIKELY(spice_util_get_debug())) \ + g_debug(G_STRLOC " " fmt, ## __VA_ARGS__); \ + } while (0) + +#define SPICE_RESERVED_PADDING (10 * sizeof(void*)) + +/* need to be in a public header */ +#ifndef SPICE_GNUC_DEPRECATED_FOR +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define SPICE_GNUC_DEPRECATED_FOR(f) \ + __attribute__((deprecated("Use " #f " instead"))) +#else +#define SPICE_GNUC_DEPRECATED_FOR(f) G_GNUC_DEPRECATED +#endif /* __GNUC__ */ +#endif + +#ifndef SPICE_NO_DEPRECATED +#define SPICE_DEPRECATED_FOR(f) SPICE_GNUC_DEPRECATED_FOR(f) +#define SPICE_DEPRECATED G_GNUC_DEPRECATED +#else +#define SPICE_DEPRECATED_FOR(f) +#define SPICE_DEPRECATED +#endif + +G_END_DECLS + +#endif /* SPICE_UTIL_H */ diff --git a/src/spice-version.h b/src/spice-version.h new file mode 100644 index 0000000..5448b00 --- /dev/null +++ b/src/spice-version.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_VERSION_H__ +#define __SPICE_VERSION_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +/** + * SECTION:spice-version + * @short_description: Spice-Gtk version checking + * @title: Version Information + * @include: spice-version.h + * + * Spice-Gtk provides macros to check the version of the library + * at compile-time + */ + +/** + * SPICE_GTK_MAJOR_VERSION: + * + * Spice-Gtk major version component (e.g. 1 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MAJOR_VERSION (0) + +/** + * SPICE_GTK_MINOR_VERSION: + * + * Spice-Gtk minor version component (e.g. 2 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MINOR_VERSION (32) + +/** + * SPICE_GTK_MICRO_VERSION: + * + * Spice-Gtk micro version component (e.g. 3 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MICRO_VERSION (0) + +/** + * SPICE_GTK_CHECK_VERSION: + * @major: required major version + * @minor: required minor version + * @micro: required micro version + * + * Compile-time version checking. Evaluates to %TRUE if the version + * of Spice-Gtk is greater than the required one. + * Since: 0.24 + */ +#define SPICE_GTK_CHECK_VERSION(major, minor, micro) \ + (SPICE_GTK_MAJOR_VERSION > (major) || \ + (SPICE_GTK_MAJOR_VERSION == (major) && SPICE_GTK_MINOR_VERSION > (minor)) || \ + (SPICE_GTK_MAJOR_VERSION == (major) && SPICE_GTK_MINOR_VERSION == (minor) && \ + SPICE_GTK_MICRO_VERSION >= (micro))) + + +#endif /* __SPICE_VERSION_H__ */ diff --git a/src/spice-version.h.in b/src/spice-version.h.in new file mode 100644 index 0000000..2314022 --- /dev/null +++ b/src/spice-version.h.in @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_VERSION_H__ +#define __SPICE_VERSION_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +/** + * SECTION:spice-version + * @short_description: Spice-Gtk version checking + * @title: Version Information + * @include: spice-version.h + * + * Spice-Gtk provides macros to check the version of the library + * at compile-time + */ + +/** + * SPICE_GTK_MAJOR_VERSION: + * + * Spice-Gtk major version component (e.g. 1 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MAJOR_VERSION (@SPICE_GTK_MAJOR_VERSION@) + +/** + * SPICE_GTK_MINOR_VERSION: + * + * Spice-Gtk minor version component (e.g. 2 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MINOR_VERSION (@SPICE_GTK_MINOR_VERSION@) + +/** + * SPICE_GTK_MICRO_VERSION: + * + * Spice-Gtk micro version component (e.g. 3 if version is 1.2.3) + * Since: 0.24 + */ +#define SPICE_GTK_MICRO_VERSION (@SPICE_GTK_MICRO_VERSION@) + +/** + * SPICE_GTK_CHECK_VERSION: + * @major: required major version + * @minor: required minor version + * @micro: required micro version + * + * Compile-time version checking. Evaluates to %TRUE if the version + * of Spice-Gtk is greater than the required one. + * Since: 0.24 + */ +#define SPICE_GTK_CHECK_VERSION(major, minor, micro) \ + (SPICE_GTK_MAJOR_VERSION > (major) || \ + (SPICE_GTK_MAJOR_VERSION == (major) && SPICE_GTK_MINOR_VERSION > (minor)) || \ + (SPICE_GTK_MAJOR_VERSION == (major) && SPICE_GTK_MINOR_VERSION == (minor) && \ + SPICE_GTK_MICRO_VERSION >= (micro))) + + +#endif /* __SPICE_VERSION_H__ */ diff --git a/src/spice-widget-cairo.c b/src/spice-widget-cairo.c new file mode 100644 index 0000000..0e84649 --- /dev/null +++ b/src/spice-widget-cairo.c @@ -0,0 +1,137 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-widget.h" +#include "spice-widget-priv.h" +#include "spice-gtk-session-priv.h" + + +G_GNUC_INTERNAL +int spice_cairo_image_create(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + if (d->canvas.surface != NULL) + return 0; + + if (d->canvas.format == SPICE_SURFACE_FMT_16_555 || + d->canvas.format == SPICE_SURFACE_FMT_16_565) { + d->canvas.convert = TRUE; + d->canvas.data = g_malloc0(d->area.width * d->area.height * 4); + + d->canvas.surface = cairo_image_surface_create_for_data + (d->canvas.data, CAIRO_FORMAT_RGB24, + d->area.width, d->area.height, d->area.width * 4); + + } else { + d->canvas.convert = FALSE; + + d->canvas.surface = cairo_image_surface_create_for_data + (d->canvas.data, CAIRO_FORMAT_RGB24, + d->canvas.width, d->canvas.height, d->canvas.stride); + } + + return 0; +} + +G_GNUC_INTERNAL +void spice_cairo_image_destroy(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + g_clear_pointer(&d->canvas.surface, cairo_surface_destroy); + if (d->canvas.convert) + g_clear_pointer(&d->canvas.data, g_free); + d->canvas.convert = FALSE; +} + +G_GNUC_INTERNAL +void spice_cairo_draw_event(SpiceDisplay *display, cairo_t *cr) +{ + SpiceDisplayPrivate *d = display->priv; + cairo_rectangle_int_t rect; + cairo_region_t *region; + double s; + int x, y; + int ww, wh; + int w, h; + + spice_display_get_scaling(display, &s, &x, &y, &w, &h); + + ww = gtk_widget_get_allocated_width(GTK_WIDGET(display)); + wh = gtk_widget_get_allocated_height(GTK_WIDGET(display)); + + /* We need to paint the bg color around the image */ + rect.x = 0; + rect.y = 0; + rect.width = ww; + rect.height = wh; + region = cairo_region_create_rectangle(&rect); + + /* Optionally cut out the inner area where the pixmap + will be drawn. This avoids 'flashing' since we're + not double-buffering. */ + if (d->canvas.surface) { + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + cairo_region_subtract_rectangle(region, &rect); + } + + gdk_cairo_region (cr, region); + cairo_region_destroy (region); + + /* Need to set a real solid color, because the default is usually + transparent these days, and non-double buffered windows can't + render transparently */ + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill(cr); + + /* Draw the display */ + if (d->canvas.surface) { + cairo_translate(cr, x, y); + cairo_rectangle(cr, 0, 0, w, h); + cairo_scale(cr, s, s); + if (!d->canvas.convert) + cairo_translate(cr, -d->area.x, -d->area.y); + cairo_set_source_surface(cr, d->canvas.surface, 0, 0); + cairo_fill(cr); + + if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER && + d->mouse_guest_x != -1 && d->mouse_guest_y != -1 && + !d->show_cursor && + spice_gtk_session_get_pointer_grabbed(d->gtk_session)) { + GdkPixbuf *image = d->mouse_pixbuf; + if (image != NULL) { + gdk_cairo_set_source_pixbuf(cr, image, + d->mouse_guest_x - d->mouse_hotspot.x, + d->mouse_guest_y - d->mouse_hotspot.y); + cairo_paint(cr); + } + } + } +} + +G_GNUC_INTERNAL +gboolean spice_cairo_is_scaled(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + return d->allow_scaling; +} diff --git a/src/spice-widget-egl.c b/src/spice-widget-egl.c new file mode 100644 index 0000000..0698af3 --- /dev/null +++ b/src/spice-widget-egl.c @@ -0,0 +1,681 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014-2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include + +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES + +#include "spice-widget.h" +#include "spice-widget-priv.h" +#include "spice-gtk-session-priv.h" +#include + +#include +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + +#define VERTS_ARRAY_SIZE (sizeof(GLfloat) * 4 * 4) +#define TEX_ARRAY_SIZE (sizeof(GLfloat) * 4 * 2) + +static const char *spice_egl_vertex_src = \ +" \ + #version 130\n \ + \ + in vec4 position; \ + in vec2 texcoords; \ + out vec2 tcoords; \ + uniform mat4 mproj; \ + \ + void main() \ + { \ + tcoords = texcoords; \ + gl_Position = mproj * position; \ + } \ +"; + +static const char *spice_egl_fragment_src = \ +" \ + #version 130\n \ + \ + in vec2 tcoords; \ + out vec4 fragmentColor; \ + uniform sampler2D samp; \ + \ + void main() \ + { \ + fragmentColor = texture2D(samp, tcoords); \ + } \ +"; + +static void apply_ortho(guint mproj, float left, float right, + float bottom, float top, float near, float far) + +{ + float a = 2.0f / (right - left); + float b = 2.0f / (top - bottom); + float c = -2.0f / (far - near); + + float tx = - (right + left) / (right - left); + float ty = - (top + bottom) / (top - bottom); + float tz = - (far + near) / (far - near); + + float ortho[16] = { + a, 0, 0, 0, + 0, b, 0, 0, + 0, 0, c, 0, + tx, ty, tz, 1 + }; + + glUniformMatrix4fv(mproj, 1, GL_FALSE, &ortho[0]); +} + +static gboolean spice_egl_init_shaders(SpiceDisplay *display, GError **err) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + GLuint fs = 0, vs = 0, buf; + GLint status, tex_loc, prog; + gboolean success = FALSE; + gchar log[1000] = { 0, }; + GLsizei len; + + glGetIntegerv(GL_CURRENT_PROGRAM, &prog); + + fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, (const char **)&spice_egl_fragment_src, NULL); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &status); + if (!status) { + glGetShaderInfoLog(fs, sizeof(log), &len, log); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "failed to compile fragment shader: %s", log); + goto end; + } + + vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, (const char **)&spice_egl_vertex_src, NULL); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &status); + if (!status) { + glGetShaderInfoLog(vs, sizeof(log), &len, log); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "failed to compile vertex shader: %s", log); + goto end; + } + + d->egl.prog = glCreateProgram(); + glAttachShader(d->egl.prog, fs); + glAttachShader(d->egl.prog, vs); + glLinkProgram(d->egl.prog); + glGetProgramiv(d->egl.prog, GL_LINK_STATUS, &status); + if (!status) { + glGetProgramInfoLog(d->egl.prog, 1000, &len, log); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "error linking shaders: %s", log); + goto end; + } + + glUseProgram(d->egl.prog); + glDetachShader(d->egl.prog, fs); + glDetachShader(d->egl.prog, vs); + + d->egl.attr_pos = glGetAttribLocation(d->egl.prog, "position"); + g_assert(d->egl.attr_pos != -1); + d->egl.attr_tex = glGetAttribLocation(d->egl.prog, "texcoords"); + g_assert(d->egl.attr_tex != -1); + tex_loc = glGetUniformLocation(d->egl.prog, "samp"); + g_assert(tex_loc != -1); + d->egl.mproj = glGetUniformLocation(d->egl.prog, "mproj"); + g_assert(d->egl.mproj != -1); + + glUniform1i(tex_loc, 0); + + /* we only use one VAO, so we always keep it bound */ + glGenVertexArrays(1, &buf); + glBindVertexArray(buf); + + glGenBuffers(1, &buf); + glBindBuffer(GL_ARRAY_BUFFER, buf); + glBufferData(GL_ARRAY_BUFFER, + VERTS_ARRAY_SIZE + TEX_ARRAY_SIZE, + NULL, + GL_STATIC_DRAW); + d->egl.vbuf_id = buf; + + glGenTextures(1, &d->egl.tex_id); + glGenTextures(1, &d->egl.tex_pointer_id); + + success = TRUE; + +end: + if (fs) { + glDeleteShader(fs); + } + if (vs) { + glDeleteShader(vs); + } + + glUseProgram(prog); + return success; +} + +G_GNUC_INTERNAL +gboolean spice_egl_init(SpiceDisplay *display, GError **err) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + static const EGLint conf_att[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_NONE, + }; + static const EGLint ctx_att[] = { +#ifdef EGL_CONTEXT_MAJOR_VERSION + EGL_CONTEXT_MAJOR_VERSION, 3, +#else + EGL_CONTEXT_CLIENT_VERSION, 3, +#endif + EGL_NONE + }; + EGLBoolean b; + EGLint major, minor, n; + EGLNativeDisplayType dpy = 0; + GdkDisplay *gdk_dpy = gdk_display_get_default(); + +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY(gdk_dpy)) { + d->egl.ctx = eglGetCurrentContext(); + dpy = (EGLNativeDisplayType)gdk_wayland_display_get_wl_display(gdk_dpy); + d->egl.display = eglGetDisplay(dpy); + goto end; + } +#endif +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY(gdk_dpy)) { + dpy = (EGLNativeDisplayType)gdk_x11_display_get_xdisplay(gdk_dpy); + } +#endif + + d->egl.display = eglGetDisplay(dpy); + if (d->egl.display == EGL_NO_DISPLAY) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "failed to get EGL display"); + return FALSE; + } + + if (!eglInitialize(d->egl.display, &major, &minor)) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "failed to init EGL display"); + return FALSE; + } + + SPICE_DEBUG("EGL major/minor: %d.%d\n", major, minor); + SPICE_DEBUG("EGL version: %s\n", + eglQueryString(d->egl.display, EGL_VERSION)); + SPICE_DEBUG("EGL vendor: %s\n", + eglQueryString(d->egl.display, EGL_VENDOR)); + SPICE_DEBUG("EGL extensions: %s\n", + eglQueryString(d->egl.display, EGL_EXTENSIONS)); + + b = eglBindAPI(EGL_OPENGL_API); + if (!b) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "cannot bind OpenGL API"); + return FALSE; + } + + b = eglChooseConfig(d->egl.display, conf_att, &d->egl.conf, + 1, &n); + + if (!b || n != 1) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "cannot find suitable EGL config"); + return FALSE; + } + + d->egl.ctx = eglCreateContext(d->egl.display, + d->egl.conf, + EGL_NO_CONTEXT, + ctx_att); + if (!d->egl.ctx) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "cannot create EGL context"); + return FALSE; + } + + eglMakeCurrent(d->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + d->egl.ctx); + +#ifdef GDK_WINDOWING_WAYLAND +end: +#endif + + if (!spice_egl_init_shaders(display, err)) + return FALSE; + + d->egl.context_ready = TRUE; + + if (spice_display_get_gl_scanout(SPICE_DISPLAY_CHANNEL(d->display)) != NULL) { + SPICE_DEBUG("scanout present during egl init, updating widget"); + spice_display_widget_gl_scanout(display); + spice_display_widget_update_monitor_area(display); + } + + return TRUE; +} + +static gboolean +gl_make_current(SpiceDisplay *display, GError **err) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + EGLBoolean success = eglMakeCurrent(d->egl.display, + d->egl.surface, + d->egl.surface, + d->egl.ctx); + if (success != EGL_TRUE) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + "failed to activate context"); + return FALSE; + } + } +#if GTK_CHECK_VERSION(3,16,0) + else { + GtkWidget *area = gtk_stack_get_child_by_name(d->stack, "gl-area"); + + gtk_gl_area_make_current(GTK_GL_AREA(area)); + } +#endif + + return TRUE; +} + +static gboolean spice_widget_init_egl_win(SpiceDisplay *display, GdkWindow *win, + GError **err) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + EGLNativeWindowType native = 0; + + if (d->egl.surface) + return TRUE; + +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_WINDOW(win)) { + native = (EGLNativeWindowType)GDK_WINDOW_XID(win); + } +#endif + + if (!native) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "this platform isn't supported"); + return FALSE; + } + + d->egl.surface = eglCreateWindowSurface(d->egl.display, + d->egl.conf, + native, NULL); + + if (!d->egl.surface) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "failed to init egl surface"); + return FALSE; + } + + if (!gl_make_current(display, err)) + return FALSE; + + return TRUE; +} + +G_GNUC_INTERNAL +gboolean spice_egl_realize_display(SpiceDisplay *display, GdkWindow *win, GError **err) +{ + SPICE_DEBUG("egl realize"); + if (!spice_widget_init_egl_win(display, win, err)) + return FALSE; + + spice_egl_resize_display(display, gdk_window_get_width(win), + gdk_window_get_height(win)); + + return TRUE; +} + +G_GNUC_INTERNAL +void spice_egl_unrealize_display(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + + SPICE_DEBUG("egl unrealize %p", d->egl.surface); + + if (!gl_make_current(display, NULL)) + return; + + if (d->egl.image != NULL) { + eglDestroyImageKHR(d->egl.display, d->egl.image); + d->egl.image = NULL; + } + + if (d->egl.tex_id) { + glDeleteTextures(1, &d->egl.tex_id); + d->egl.tex_id = 0; + } + + if (d->egl.tex_pointer_id) { + glDeleteTextures(1, &d->egl.tex_pointer_id); + d->egl.tex_pointer_id = 0; + } + + if (d->egl.vbuf_id) { + glDeleteBuffers(1, &d->egl.vbuf_id); + d->egl.vbuf_id = 0; + } + + if (d->egl.prog) { + glDeleteProgram(d->egl.prog); + d->egl.prog = 0; + } + + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + /* egl.surface && egl.ctx are only created on x11, see + spice_egl_init() */ + + if (d->egl.surface != EGL_NO_SURFACE) { + eglDestroySurface(d->egl.display, d->egl.surface); + d->egl.surface = EGL_NO_SURFACE; + } + + if (d->egl.ctx) { + eglDestroyContext(d->egl.display, d->egl.ctx); + d->egl.ctx = 0; + } + + eglMakeCurrent(d->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + /* do not call eglterminate() since egl may be used by + * somebody else code */ + } +} + +G_GNUC_INTERNAL +void spice_egl_resize_display(SpiceDisplay *display, int w, int h) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + int prog; + + if (!gl_make_current(display, NULL)) + return; + + glGetIntegerv(GL_CURRENT_PROGRAM, &prog); + + glUseProgram(d->egl.prog); + apply_ortho(d->egl.mproj, 0, w, 0, h, -1, 1); + glViewport(0, 0, w, h); + + if (d->ready) + spice_egl_update_display(display); + + glUseProgram(prog); +} + +static void +draw_rect_from_arrays(SpiceDisplay *display, const void *verts, const void *tex) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + + glBindBuffer(GL_ARRAY_BUFFER, d->egl.vbuf_id); + + if (verts) { + glEnableVertexAttribArray(d->egl.attr_pos); + glBufferSubData(GL_ARRAY_BUFFER, + 0, + VERTS_ARRAY_SIZE, + verts); + glVertexAttribPointer(d->egl.attr_pos, 4, GL_FLOAT, + GL_FALSE, 0, 0); + } + if (tex) { + glEnableVertexAttribArray(d->egl.attr_tex); + glBufferSubData(GL_ARRAY_BUFFER, + VERTS_ARRAY_SIZE, + TEX_ARRAY_SIZE, + tex); + glVertexAttribPointer(d->egl.attr_tex, 2, GL_FLOAT, + GL_FALSE, 0, + (void *)VERTS_ARRAY_SIZE); + } + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (verts) + glDisableVertexAttribArray(d->egl.attr_pos); + if (tex) + glDisableVertexAttribArray(d->egl.attr_tex); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static GLvoid +client_draw_rect_tex(SpiceDisplay *display, + float x, float y, float w, float h, + float tx, float ty, float tw, float th) +{ + float verts[4][4]; + float tex[4][2]; + + verts[0][0] = x; + verts[0][1] = y; + verts[0][2] = 0.0; + verts[0][3] = 1.0; + tex[0][0] = tx; + tex[0][1] = ty; + verts[1][0] = x + w; + verts[1][1] = y; + verts[1][2] = 0.0; + verts[1][3] = 1.0; + tex[1][0] = tx + tw; + tex[1][1] = ty; + verts[2][0] = x; + verts[2][1] = y + h; + verts[2][2] = 0.0; + verts[2][3] = 1.0; + tex[2][0] = tx; + tex[2][1] = ty + th; + verts[3][0] = x + w; + verts[3][1] = y + h; + verts[3][2] = 0.0; + verts[3][3] = 1.0; + tex[3][0] = tx + tw; + tex[3][1] = ty + th; + + draw_rect_from_arrays(display, verts, tex); +} + +G_GNUC_INTERNAL +void spice_egl_cursor_set(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + GdkPixbuf *image = d->mouse_pixbuf; + + g_return_if_fail(d->egl.enabled); + + if (image == NULL) + return; + + int width = gdk_pixbuf_get_width(image); + int height = gdk_pixbuf_get_height(image); + + glBindTexture(GL_TEXTURE_2D, d->egl.tex_pointer_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, + gdk_pixbuf_read_pixels(image)); + glBindTexture(GL_TEXTURE_2D, 0); +} + +G_GNUC_INTERNAL +void spice_egl_update_display(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + double s; + int x, y, w, h; + gdouble tx, ty, tw, th; + int prog; + + g_return_if_fail(d->ready); + if (!gl_make_current(display, NULL)) + return; + + spice_display_get_scaling(display, &s, &x, &y, &w, &h); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + tx = ((float)d->area.x / (float)d->egl.scanout.width); + ty = ((float)d->area.y / (float)d->egl.scanout.height); + tw = ((float)d->area.width / (float)d->egl.scanout.width); + th = ((float)d->area.height / (float)d->egl.scanout.height); + + /* convert to opengl coordinates, 0 is bottom, 1 is top. ty should + * be the bottom of the area, since th is upward */ + /* 1+---------------+ */ + /* | | */ + /* | ty to |th | */ + /* | | -> | | */ + /* | |th ty | */ + /* | | */ + /* | | */ + /* +---------------+ */ + /* 0 */ + ty = 1 - (ty + th); + + + /* if the scanout is inverted, then invert coordinates and direction too */ + if (!d->egl.scanout.y0top) { + ty = 1 - ty; + th = -1 * th; + } + SPICE_DEBUG("update %f +%d+%d %dx%d +%f+%f %fx%f", s, x, y, w, h, + tx, ty, tw, th); + glBindTexture(GL_TEXTURE_2D, d->egl.tex_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + +#if !GTK_CHECK_VERSION(3,16,0) + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)d->egl.image); +#endif + + glDisable(GL_BLEND); + glGetIntegerv(GL_CURRENT_PROGRAM, &prog); + glUseProgram(d->egl.prog); + client_draw_rect_tex(display, x, y, w, h, + tx, ty, tw, th); + + if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER && + d->mouse_guest_x != -1 && d->mouse_guest_y != -1 && + !d->show_cursor && + spice_gtk_session_get_pointer_grabbed(d->gtk_session) && + d->mouse_pixbuf != NULL) { + GdkPixbuf *image = d->mouse_pixbuf; + int width = gdk_pixbuf_get_width(image); + int height = gdk_pixbuf_get_height(image); + + glBindTexture(GL_TEXTURE_2D, d->egl.tex_pointer_id); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + client_draw_rect_tex(display, + x + (d->mouse_guest_x - d->mouse_hotspot.x) * s, + y + h - (d->mouse_guest_y - d->mouse_hotspot.y) * s, + width, -height, + 0, 0, 1, 1); + } + + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + /* gtk+ does the swap with gtkglarea */ + eglSwapBuffers(d->egl.display, d->egl.surface); + } + + glUseProgram(prog); +} + +G_GNUC_INTERNAL +gboolean spice_egl_update_scanout(SpiceDisplay *display, + const SpiceGlScanout *scanout, + GError **err) +{ + SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display); + EGLint attrs[13]; + guint32 format; + + g_return_val_if_fail(scanout != NULL, FALSE); + format = scanout->format; + + if (d->egl.image != NULL) { + eglDestroyImageKHR(d->egl.display, d->egl.image); + d->egl.image = NULL; + } + + if (scanout->fd == -1) + return TRUE; + + attrs[0] = EGL_DMA_BUF_PLANE0_FD_EXT; + attrs[1] = scanout->fd; + attrs[2] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attrs[3] = scanout->stride; + attrs[4] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attrs[5] = 0; + attrs[6] = EGL_WIDTH; + attrs[7] = scanout->width; + attrs[8] = EGL_HEIGHT; + attrs[9] = scanout->height; + attrs[10] = EGL_LINUX_DRM_FOURCC_EXT; + attrs[11] = format; + attrs[12] = EGL_NONE; + SPICE_DEBUG("fd:%d stride:%u y0:%d %ux%u format:0x%x (%c%c%c%c)", + scanout->fd, scanout->stride, scanout->y0top, + scanout->width, scanout->height, format, + (int)format & 0xff, (int)(format >> 8) & 0xff, + (int)(format >> 16) & 0xff, (int)format >> 24); + + d->egl.image = eglCreateImageKHR(d->egl.display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + (EGLClientBuffer)NULL, + attrs); + + d->egl.scanout = *scanout; + +#if GTK_CHECK_VERSION(3,16,0) + if (!gl_make_current(display, NULL)) + return FALSE; + + glBindTexture(GL_TEXTURE_2D, d->egl.tex_id); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)d->egl.image); +#endif + + return TRUE; +} diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h new file mode 100644 index 0000000..e36baf3 --- /dev/null +++ b/src/spice-widget-priv.h @@ -0,0 +1,171 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_WIDGET_PRIV_H__ +#define __SPICE_WIDGET_PRIV_H__ + +#include "config.h" + +#ifdef WIN32 +#include +#endif + +#ifndef G_OS_WIN32 +#include +#endif + +#include "spice-widget.h" +#include "spice-common.h" +#include "spice-gtk-session.h" + +G_BEGIN_DECLS + +typedef struct _SpiceDisplayPrivate SpiceDisplayPrivate; + +struct _SpiceDisplay { + GtkEventBox parent; + SpiceDisplayPrivate *priv; +}; + +struct _SpiceDisplayClass { + GtkEventBoxClass parent_class; + + /* signals */ + void (*mouse_grab)(SpiceChannel *channel, gint grabbed); + void (*keyboard_grab)(SpiceChannel *channel, gint grabbed); +}; + +#define SPICE_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_DISPLAY, SpiceDisplayPrivate)) + +struct _SpiceDisplayPrivate { + GtkStack *stack; + gint channel_id; + gint monitor_id; + + /* options */ + bool keyboard_grab_enable; + gboolean keyboard_grab_inhibit; + bool mouse_grab_enable; + bool resize_guest_enable; + + /* state */ + gboolean ready; + gboolean monitor_ready; + struct { + enum SpiceSurfaceFmt format; + gint width, height, stride; + gpointer data_origin; /* the original display image data */ + gpointer data; /* converted if necessary to 32 bits */ + bool convert; + cairo_surface_t *surface; + } canvas; + GdkRectangle area; + /* window border */ + gint ww, wh, mx, my; + + gboolean allow_scaling; + gboolean only_downscale; + gboolean disable_inputs; + + SpiceSession *session; + SpiceGtkSession *gtk_session; + SpiceMainChannel *main; + SpiceChannel *display; + SpiceCursorChannel *cursor; + SpiceInputsChannel *inputs; + SpiceSmartcardChannel *smartcard; + + enum SpiceMouseMode mouse_mode; + int mouse_grab_active; + bool mouse_have_pointer; + GdkCursor *mouse_cursor; + GdkPixbuf *mouse_pixbuf; + GdkPoint mouse_hotspot; + GdkCursor *show_cursor; + int mouse_last_x; + int mouse_last_y; + int mouse_guest_x; + int mouse_guest_y; + + bool keyboard_grab_active; + bool keyboard_have_focus; + + const guint16 *keycode_map; + size_t keycode_maplen; + uint32_t key_state[512 / 32]; + int key_delayed_scancode; + guint key_delayed_id; + SpiceGrabSequence *grabseq; /* the configured key sequence */ + gboolean *activeseq; /* the currently pressed keys */ + gboolean seq_pressed; + gboolean keyboard_grab_released; + gint mark; +#ifdef WIN32 + HHOOK keyboard_hook; + int win_mouse[3]; + int win_mouse_speed; +#endif + guint keypress_delay; + gint zoom_level; +#ifdef GDK_WINDOWING_X11 + int x11_accel_numerator; + int x11_accel_denominator; + int x11_threshold; +#endif +#ifndef G_OS_WIN32 + struct { + gboolean context_ready; + gboolean enabled; + EGLSurface surface; + EGLDisplay display; + EGLConfig conf; + EGLContext ctx; + gint mproj, attr_pos, attr_tex; + guint vbuf_id; + guint tex_id; + guint tex_pointer_id; + guint prog; + EGLImageKHR image; + gboolean call_draw_done; + SpiceGlScanout scanout; + } egl; +#endif +}; + +int spice_cairo_image_create (SpiceDisplay *display); +void spice_cairo_image_destroy (SpiceDisplay *display); +void spice_cairo_draw_event (SpiceDisplay *display, cairo_t *cr); +gboolean spice_cairo_is_scaled (SpiceDisplay *display); +void spice_display_get_scaling (SpiceDisplay *display, double *s, int *x, int *y, int *w, int *h); +gboolean spice_egl_init (SpiceDisplay *display, GError **err); +gboolean spice_egl_realize_display (SpiceDisplay *display, GdkWindow *win, + GError **err); +void spice_egl_unrealize_display (SpiceDisplay *display); +void spice_egl_update_display (SpiceDisplay *display); +void spice_egl_resize_display (SpiceDisplay *display, int w, int h); +gboolean spice_egl_update_scanout (SpiceDisplay *display, + const SpiceGlScanout *scanout, + GError **err); +void spice_egl_cursor_set (SpiceDisplay *display); + +void spice_display_widget_gl_scanout (SpiceDisplay *display); +void spice_display_widget_update_monitor_area(SpiceDisplay *display); + +G_END_DECLS + +#endif diff --git a/src/spice-widget.c b/src/spice-widget.c new file mode 100644 index 0000000..c5353af --- /dev/null +++ b/src/spice-widget.c @@ -0,0 +1,2922 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include +#include + +#ifdef HAVE_X11_XKBLIB_H +#include +#include +#endif +#ifdef GDK_WINDOWING_X11 +#include +#include +#endif +#ifdef G_OS_WIN32 +#include +#include +#include +#include +#ifndef MAPVK_VK_TO_VSC /* may be undefined in older mingw-headers */ +#define MAPVK_VK_TO_VSC 0 +#endif +#endif + +#include "spice-widget.h" +#include "spice-widget-priv.h" +#include "spice-gtk-session-priv.h" +#include "vncdisplaykeymap.h" +#include "spice-grabsequence-priv.h" + +/* Some compatibility defines to let us build on both Gtk2 and Gtk3 */ + +/** + * SECTION:spice-widget + * @short_description: a GTK display widget + * @title: Spice Display + * @section_id: + * @stability: Stable + * @include: spice-client-gtk.h + * + * A GTK widget that displays a SPICE server. It sends keyboard/mouse + * events and can also share clipboard... + * + * Arbitrary key events can be sent thanks to spice_display_send_keys(). + * + * The widget will optionally grab the keyboard and the mouse when + * focused if the properties #SpiceDisplay:grab-keyboard and + * #SpiceDisplay:grab-mouse are #TRUE respectively. It can be + * ungrabbed with spice_display_mouse_ungrab(), and by setting a key + * combination with spice_display_set_grab_keys(). + * + * Finally, spice_display_get_pixbuf() will take a screenshot of the + * current display and return an #GdkPixbuf (that you can then easily + * save to disk). + */ + +G_DEFINE_TYPE(SpiceDisplay, spice_display, GTK_TYPE_EVENT_BOX) + +/* Properties */ +enum { + PROP_0, + PROP_SESSION, + PROP_CHANNEL_ID, + PROP_KEYBOARD_GRAB, + PROP_MOUSE_GRAB, + PROP_RESIZE_GUEST, + PROP_SCALING, + PROP_ONLY_DOWNSCALE, + PROP_DISABLE_INPUTS, + PROP_ZOOM_LEVEL, + PROP_MONITOR_ID, + PROP_KEYPRESS_DELAY, + PROP_READY +}; + +/* Signals */ +enum { + SPICE_DISPLAY_MOUSE_GRAB, + SPICE_DISPLAY_KEYBOARD_GRAB, + SPICE_DISPLAY_GRAB_KEY_PRESSED, + SPICE_DISPLAY_LAST_SIGNAL, +}; + +static guint signals[SPICE_DISPLAY_LAST_SIGNAL]; + +#ifdef G_OS_WIN32 +static HWND win32_window = NULL; +#endif + +static void update_keyboard_grab(SpiceDisplay *display); +static void try_keyboard_grab(SpiceDisplay *display); +static void try_keyboard_ungrab(SpiceDisplay *display); +static void update_mouse_grab(SpiceDisplay *display); +static void try_mouse_grab(SpiceDisplay *display); +static void try_mouse_ungrab(SpiceDisplay *display); +static void recalc_geometry(GtkWidget *widget); +static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data); +static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data); +static void cursor_invalidate(SpiceDisplay *display); +static void update_area(SpiceDisplay *display, gint x, gint y, gint width, gint height); +static void release_keys(SpiceDisplay *display); +static void size_allocate(GtkWidget *widget, GtkAllocation *conf, gpointer data); +static gboolean draw_event(GtkWidget *widget, cairo_t *cr, gpointer data); +static void update_size_request(SpiceDisplay *display); + +/* ---------------------------------------------------------------- */ + +static void spice_display_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceDisplay *display = SPICE_DISPLAY(object); + SpiceDisplayPrivate *d = display->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, d->session); + break; + case PROP_CHANNEL_ID: + g_value_set_int(value, d->channel_id); + break; + case PROP_MONITOR_ID: + g_value_set_int(value, d->monitor_id); + break; + case PROP_KEYBOARD_GRAB: + g_value_set_boolean(value, d->keyboard_grab_enable); + break; + case PROP_MOUSE_GRAB: + g_value_set_boolean(value, d->mouse_grab_enable); + break; + case PROP_RESIZE_GUEST: + g_value_set_boolean(value, d->resize_guest_enable); + break; + case PROP_SCALING: + g_value_set_boolean(value, d->allow_scaling); + break; + case PROP_ONLY_DOWNSCALE: + g_value_set_boolean(value, d->only_downscale); + break; + case PROP_DISABLE_INPUTS: + g_value_set_boolean(value, d->disable_inputs); + break; + case PROP_ZOOM_LEVEL: + g_value_set_int(value, d->zoom_level); + break; + case PROP_READY: + g_value_set_boolean(value, d->ready); + break; + case PROP_KEYPRESS_DELAY: + g_value_set_uint(value, d->keypress_delay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void scaling_updated(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(display)); + + recalc_geometry(GTK_WIDGET(display)); + if (d->canvas.surface && window) { /* if not yet shown */ + gtk_widget_queue_draw(GTK_WIDGET(display)); + } + update_size_request(display); +} + +static void update_size_request(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + gint reqwidth, reqheight; + + if (d->resize_guest_enable || d->allow_scaling) { + reqwidth = 640; + reqheight = 480; + } else { + reqwidth = d->area.width; + reqheight = d->area.height; + } + + gtk_widget_set_size_request(GTK_WIDGET(display), reqwidth, reqheight); + recalc_geometry(GTK_WIDGET(display)); +} + +static void update_keyboard_focus(SpiceDisplay *display, gboolean state) +{ + SpiceDisplayPrivate *d = display->priv; + + d->keyboard_have_focus = state; + spice_gtk_session_set_keyboard_has_focus(d->gtk_session, state); + + /* keyboard grab gets inhibited by usb-device-manager when it is + in the process of redirecting a usb-device (as this may show a + policykit dialog). Making autoredir/automount setting changes while + this is happening is not a good idea! */ + if (d->keyboard_grab_inhibit) + return; + + spice_gtk_session_request_auto_usbredir(d->gtk_session, state); +} + +static gint get_display_id(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + /* supported monitor_id only with display channel #0 */ + if (d->channel_id == 0 && d->monitor_id >= 0) + return d->monitor_id; + + g_return_val_if_fail(d->monitor_id <= 0, -1); + + return d->channel_id; +} + +static bool egl_enabled(SpiceDisplayPrivate *d) +{ +#ifndef G_OS_WIN32 + return d->egl.enabled; +#else + return false; +#endif +} + +static void update_ready(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + gboolean ready = FALSE; + + if (d->monitor_ready) { + ready = egl_enabled(d) || d->mark != 0; + } + /* If the 'resize-guest' property is set, the application expects spice-gtk + * to manage the size and state of the displays, so update the 'enabled' + * state here. If 'resize-guest' is false, we can assume that the + * application will manage the state of the displays. + */ + if (d->resize_guest_enable) { + spice_main_update_display_enabled(d->main, get_display_id(display), + ready, TRUE); + } + + if (d->ready == ready) + return; + + if (ready && gtk_widget_get_window(GTK_WIDGET(display))) + gtk_widget_queue_draw(GTK_WIDGET(display)); + + d->ready = ready; + g_object_notify(G_OBJECT(display), "ready"); +} + +static void set_monitor_ready(SpiceDisplay *self, gboolean ready) +{ + SpiceDisplayPrivate *d = self->priv; + + d->monitor_ready = ready; + update_ready(self); +} + +G_GNUC_INTERNAL +void spice_display_widget_update_monitor_area(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + SpiceDisplayMonitorConfig *cfg, *c = NULL; + GArray *monitors = NULL; + int i; + + SPICE_DEBUG("update monitor area %d:%d", d->channel_id, d->monitor_id); + if (d->monitor_id < 0) + goto whole; + + g_object_get(d->display, "monitors", &monitors, NULL); + for (i = 0; monitors != NULL && i < monitors->len; i++) { + cfg = &g_array_index(monitors, SpiceDisplayMonitorConfig, i); + if (cfg->id == d->monitor_id) { + c = cfg; + break; + } + } + if (c == NULL) { + SPICE_DEBUG("update monitor: no monitor %d", d->monitor_id); + set_monitor_ready(display, false); + if (spice_channel_test_capability(d->display, SPICE_DISPLAY_CAP_MONITORS_CONFIG)) { + SPICE_DEBUG("waiting until MonitorsConfig is received"); + g_clear_pointer(&monitors, g_array_unref); + return; + } + goto whole; + } + + if (c->surface_id != 0) { + g_warning("FIXME: only support monitor config with primary surface 0, " + "but given config surface %u", c->surface_id); + goto whole; + } + + /* If only one head on this monitor, update the whole area */ + if (monitors->len == 1 && !egl_enabled(d)) { + update_area(display, 0, 0, c->width, c->height); + } else { + update_area(display, c->x, c->y, c->width, c->height); + } + g_clear_pointer(&monitors, g_array_unref); + return; + +whole: + g_clear_pointer(&monitors, g_array_unref); + /* by display whole surface */ + update_area(display, 0, 0, d->canvas.width, d->canvas.height); + set_monitor_ready(display, true); +} + +static void spice_display_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceDisplay *display = SPICE_DISPLAY(object); + SpiceDisplayPrivate *d = display->priv; + + switch (prop_id) { + case PROP_SESSION: + g_warn_if_fail(d->session == NULL); + d->session = g_value_dup_object(value); + d->gtk_session = spice_gtk_session_get(d->session); + spice_g_signal_connect_object(d->gtk_session, "notify::pointer-grabbed", + G_CALLBACK(cursor_invalidate), object, + G_CONNECT_SWAPPED); + break; + case PROP_CHANNEL_ID: + d->channel_id = g_value_get_int(value); + break; + case PROP_MONITOR_ID: + d->monitor_id = g_value_get_int(value); + if (d->display) /* if constructed */ + spice_display_widget_update_monitor_area(display); + break; + case PROP_KEYBOARD_GRAB: + d->keyboard_grab_enable = g_value_get_boolean(value); + update_keyboard_grab(display); + break; + case PROP_MOUSE_GRAB: + d->mouse_grab_enable = g_value_get_boolean(value); + update_mouse_grab(display); + break; + case PROP_RESIZE_GUEST: + d->resize_guest_enable = g_value_get_boolean(value); + update_ready(display); + update_size_request(display); + break; + case PROP_SCALING: + d->allow_scaling = g_value_get_boolean(value); + scaling_updated(display); + break; + case PROP_ONLY_DOWNSCALE: + d->only_downscale = g_value_get_boolean(value); + scaling_updated(display); + break; + case PROP_DISABLE_INPUTS: + d->disable_inputs = g_value_get_boolean(value); + gtk_widget_set_can_focus(GTK_WIDGET(display), !d->disable_inputs); + update_keyboard_grab(display); + update_mouse_grab(display); + break; + case PROP_ZOOM_LEVEL: + d->zoom_level = g_value_get_int(value); + scaling_updated(display); + break; + case PROP_KEYPRESS_DELAY: + { + const gchar *env = g_getenv("SPICE_KEYPRESS_DELAY"); + guint delay = g_value_get_uint(value); + if (env != NULL) + delay = strtoul(env, NULL, 10); + + SPICE_DEBUG("keypress-delay is set to %u ms", delay); + d->keypress_delay = delay; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void session_inhibit_keyboard_grab_changed(GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + SpiceDisplay *display = user_data; + SpiceDisplayPrivate *d = display->priv; + + g_object_get(d->session, "inhibit-keyboard-grab", + &d->keyboard_grab_inhibit, NULL); + update_keyboard_grab(display); + update_mouse_grab(display); +} + +static void spice_display_dispose(GObject *obj) +{ + SpiceDisplay *display = SPICE_DISPLAY(obj); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("spice display dispose"); + + spice_cairo_image_destroy(display); + g_clear_object(&d->session); + d->gtk_session = NULL; + + if (d->key_delayed_id) { + g_source_remove(d->key_delayed_id); + d->key_delayed_id = 0; + } + + G_OBJECT_CLASS(spice_display_parent_class)->dispose(obj); +} + +static void spice_display_finalize(GObject *obj) +{ + SpiceDisplay *display = SPICE_DISPLAY(obj); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("Finalize spice display"); + + g_clear_pointer(&d->grabseq, spice_grab_sequence_free); + g_clear_pointer(&d->activeseq, g_free); + + g_clear_object(&d->show_cursor); + g_clear_object(&d->mouse_cursor); + g_clear_object(&d->mouse_pixbuf); + + G_OBJECT_CLASS(spice_display_parent_class)->finalize(obj); +} + +static GdkCursor* get_blank_cursor(void) +{ + if (g_getenv("SPICE_DEBUG_CURSOR")) + return gdk_cursor_new(GDK_DOT); + + return gdk_cursor_new(GDK_BLANK_CURSOR); +} + +static gboolean grab_broken(SpiceDisplay *self, GdkEventGrabBroken *event, + gpointer user_data G_GNUC_UNUSED) +{ + SPICE_DEBUG("%s (implicit: %d, keyboard: %d)", __FUNCTION__, + event->implicit, event->keyboard); + + if (event->keyboard) { + try_keyboard_ungrab(self); + release_keys(self); + } + + /* always release mouse when grab broken, this could be more + generally placed in keyboard_ungrab(), but one might worry of + breaking someone else code. */ + try_mouse_ungrab(self); + + return false; +} + +static void drag_data_received_callback(SpiceDisplay *self, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + gpointer *user_data) +{ + const guchar *buf; + gchar **file_urls; + int n_files; + SpiceDisplayPrivate *d = self->priv; + int i = 0; + GFile **files; + + /* We get a buf like: + * file:///root/a.txt\r\nfile:///root/b.txt\r\n + */ + SPICE_DEBUG("%s: drag a file", __FUNCTION__); + buf = gtk_selection_data_get_data(data); + g_return_if_fail(buf != NULL); + + file_urls = g_uri_list_extract_uris((const gchar*)buf); + n_files = g_strv_length(file_urls); + files = g_new0(GFile*, n_files + 1); + for (i = 0; i < n_files; i++) { + files[i] = g_file_new_for_uri(file_urls[i]); + } + g_strfreev(file_urls); + + spice_main_file_copy_async(d->main, files, 0, NULL, NULL, + NULL, NULL, NULL); + for (i = 0; i < n_files; i++) { + g_object_unref(files[i]); + } + g_free(files); + + gtk_drag_finish(drag_context, TRUE, FALSE, time); +} + +static void grab_notify(SpiceDisplay *display, gboolean was_grabbed) +{ + SPICE_DEBUG("grab notify %d", was_grabbed); + + if (was_grabbed == FALSE) + release_keys(display); +} + +#if GTK_CHECK_VERSION(3,16,0) +#ifndef G_OS_WIN32 +static gboolean +gl_area_render(GtkGLArea *area, GdkGLContext *context, gpointer user_data) +{ + SpiceDisplay *display = SPICE_DISPLAY(user_data); + SpiceDisplayPrivate *d = display->priv; + + spice_egl_update_display(display); + glFlush(); + if (d->egl.call_draw_done) { + spice_display_gl_draw_done(SPICE_DISPLAY_CHANNEL(d->display)); + d->egl.call_draw_done = FALSE; + } + + return TRUE; +} + +static void +gl_area_realize(GtkGLArea *area, gpointer user_data) +{ + SpiceDisplay *display = SPICE_DISPLAY(user_data); + GError *err = NULL; + + gtk_gl_area_make_current(area); + if (gtk_gl_area_get_error(area) != NULL) + return; + + if (!spice_egl_init(display, &err)) { + g_critical("egl init failed: %s", err->message); + g_clear_error(&err); + } +} +#endif +#endif + +static void +drawing_area_realize(GtkWidget *area, gpointer user_data) +{ +#ifdef GDK_WINDOWING_X11 + SpiceDisplay *display = SPICE_DISPLAY(user_data); + GError *err = NULL; + + if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return; + + if (!spice_egl_init(display, &err)) { + g_critical("egl init failed: %s", err->message); + g_clear_error(&err); + } + + if (!spice_egl_realize_display(display, gtk_widget_get_window(area), &err)) { + g_critical("egl realize failed: %s", err->message); + g_clear_error(&err); + } +#endif +} + +static void spice_display_init(SpiceDisplay *display) +{ + GtkWidget *widget = GTK_WIDGET(display); + GtkWidget *area; + SpiceDisplayPrivate *d; + GtkTargetEntry targets = { "text/uri-list", 0, 0 }; + + d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display); + d->stack = GTK_STACK(gtk_stack_new()); + gtk_container_add(GTK_CONTAINER(display), GTK_WIDGET(d->stack)); + area = gtk_drawing_area_new(); + + g_object_connect(area, + "signal::draw", draw_event, display, + "signal::realize", drawing_area_realize, display, + NULL); + gtk_stack_add_named(d->stack, area, "draw-area"); + gtk_widget_set_double_buffered(area, true); + gtk_stack_set_visible_child(d->stack, area); + +#if GTK_CHECK_VERSION(3,16,0) +#ifndef G_OS_WIN32 + area = gtk_gl_area_new(); + gtk_gl_area_set_required_version(GTK_GL_AREA(area), 3, 2); + gtk_gl_area_set_auto_render(GTK_GL_AREA(area), false); + g_object_connect(area, + "signal::render", gl_area_render, display, + "signal::realize", gl_area_realize, display, + NULL); + gtk_stack_add_named(d->stack, area, "gl-area"); + gtk_widget_show_all(widget); +#endif +#endif + + g_signal_connect(display, "grab-broken-event", G_CALLBACK(grab_broken), NULL); + g_signal_connect(display, "grab-notify", G_CALLBACK(grab_notify), NULL); + + gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, &targets, 1, GDK_ACTION_COPY); + g_signal_connect(display, "drag-data-received", + G_CALLBACK(drag_data_received_callback), NULL); + g_signal_connect(display, "size-allocate", G_CALLBACK(size_allocate), NULL); + + gtk_widget_add_events(widget, + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON_MOTION_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | + GDK_KEY_PRESS_MASK | + GDK_SCROLL_MASK); + gtk_widget_set_can_focus(widget, true); + gtk_event_box_set_above_child(GTK_EVENT_BOX(widget), true); + + d->grabseq = spice_grab_sequence_new_from_string("Control_L+Alt_L"); + d->activeseq = g_new0(gboolean, d->grabseq->nkeysyms); + d->mouse_cursor = get_blank_cursor(); +} + +static GObject * +spice_display_constructor(GType gtype, + guint n_properties, + GObjectConstructParam *properties) +{ + GObject *obj; + SpiceDisplay *display; + SpiceDisplayPrivate *d; + GList *list; + GList *it; + + { + /* Always chain up to the parent constructor */ + GObjectClass *parent_class; + parent_class = G_OBJECT_CLASS(spice_display_parent_class); + obj = parent_class->constructor(gtype, n_properties, properties); + } + + display = SPICE_DISPLAY(obj); + d = display->priv; + + if (!d->session) + g_error("SpiceDisplay constructed without a session"); + + spice_g_signal_connect_object(d->session, "channel-new", + G_CALLBACK(channel_new), display, 0); + spice_g_signal_connect_object(d->session, "channel-destroy", + G_CALLBACK(channel_destroy), display, 0); + list = spice_session_get_channels(d->session); + for (it = g_list_first(list); it != NULL; it = g_list_next(it)) { + if (SPICE_IS_MAIN_CHANNEL(it->data)) { + channel_new(d->session, it->data, (gpointer*)display); + break; + } + } + for (it = g_list_first(list); it != NULL; it = g_list_next(it)) { + if (!SPICE_IS_MAIN_CHANNEL(it->data)) + channel_new(d->session, it->data, (gpointer*)display); + } + g_list_free(list); + + spice_g_signal_connect_object(d->session, "notify::inhibit-keyboard-grab", + G_CALLBACK(session_inhibit_keyboard_grab_changed), + display, 0); + + return obj; +} + +/** + * spice_display_set_grab_keys: + * @display: the display widget + * @seq: (transfer none): key sequence + * + * Set the key combination to grab/ungrab the keyboard. The default is + * "Control L + Alt L". + **/ +void spice_display_set_grab_keys(SpiceDisplay *display, SpiceGrabSequence *seq) +{ + SpiceDisplayPrivate *d; + + g_return_if_fail(SPICE_IS_DISPLAY(display)); + + d = display->priv; + g_return_if_fail(d != NULL); + + if (d->grabseq) { + spice_grab_sequence_free(d->grabseq); + } + if (seq) + d->grabseq = spice_grab_sequence_copy(seq); + else + d->grabseq = spice_grab_sequence_new_from_string("Control_L+Alt_L"); + g_free(d->activeseq); + d->activeseq = g_new0(gboolean, d->grabseq->nkeysyms); +} + +#ifdef G_OS_WIN32 +static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam) +{ + if (win32_window && code == HC_ACTION && wparam != WM_KEYUP) { + KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT*)lparam; + DWORD dwmsg = (hooked->flags << 24) | (hooked->scanCode << 16) | 1; + + if (hooked->vkCode == VK_NUMLOCK || hooked->vkCode == VK_RSHIFT) { + dwmsg &= ~(1 << 24); + SendMessage(win32_window, wparam, hooked->vkCode, dwmsg); + } + switch (hooked->vkCode) { + case VK_CAPITAL: + case VK_SCROLL: + case VK_NUMLOCK: + case VK_LSHIFT: + case VK_RSHIFT: + case VK_RCONTROL: + case VK_LMENU: + case VK_RMENU: + break; + case VK_LCONTROL: + /* When pressing AltGr, an extra VK_LCONTROL with a special + * scancode with bit 9 set is sent. Let's ignore the extra + * VK_LCONTROL, as that will make AltGr misbehave. */ + if (hooked->scanCode & 0x200) + return 1; + break; + default: + SendMessage(win32_window, wparam, hooked->vkCode, dwmsg); + return 1; + } + } + return CallNextHookEx(NULL, code, wparam, lparam); +} +#endif + +/** + * spice_display_get_grab_keys: + * @display: the display widget + * + * Finds the current grab key combination for the @display. + * + * Returns: (transfer none): the current grab key combination. + **/ +SpiceGrabSequence *spice_display_get_grab_keys(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d; + + g_return_val_if_fail(SPICE_IS_DISPLAY(display), NULL); + + d = display->priv; + g_return_val_if_fail(d != NULL, NULL); + + return d->grabseq; +} + +static void try_keyboard_grab(SpiceDisplay *display) +{ + GtkWidget *widget = GTK_WIDGET(display); + SpiceDisplayPrivate *d = display->priv; + GdkGrabStatus status; + + if (g_getenv("SPICE_NOGRAB")) + return; + if (d->disable_inputs) + return; + + if (d->keyboard_grab_inhibit) + return; + if (!d->keyboard_grab_enable) + return; + if (d->keyboard_grab_active) + return; + if (!spice_gtk_session_get_keyboard_has_focus(d->gtk_session)) + return; + if (!spice_gtk_session_get_mouse_has_pointer(d->gtk_session)) + return; + if (d->keyboard_grab_released) + return; + + g_return_if_fail(gtk_widget_is_focus(widget)); + + SPICE_DEBUG("grab keyboard"); + gtk_widget_grab_focus(widget); + +#ifdef G_OS_WIN32 + if (d->keyboard_hook == NULL) + d->keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_cb, + GetModuleHandle(NULL), 0); + g_warn_if_fail(d->keyboard_hook != NULL); +#endif + status = gdk_keyboard_grab(gtk_widget_get_window(widget), FALSE, + GDK_CURRENT_TIME); + if (status != GDK_GRAB_SUCCESS) { + g_warning("keyboard grab failed %u", status); + d->keyboard_grab_active = false; + } else { + d->keyboard_grab_active = true; + g_signal_emit(widget, signals[SPICE_DISPLAY_KEYBOARD_GRAB], 0, true); + } +} + +static void try_keyboard_ungrab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + GtkWidget *widget = GTK_WIDGET(display); + + if (!d->keyboard_grab_active) + return; + + SPICE_DEBUG("ungrab keyboard"); + gdk_keyboard_ungrab(GDK_CURRENT_TIME); +#ifdef G_OS_WIN32 + // do not use g_clear_pointer as Windows API have different linkage + if (d->keyboard_hook) { + UnhookWindowsHookEx(d->keyboard_hook); + d->keyboard_hook = NULL; + } +#endif + d->keyboard_grab_active = false; + g_signal_emit(widget, signals[SPICE_DISPLAY_KEYBOARD_GRAB], 0, false); +} + +static void update_keyboard_grab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + if (d->keyboard_grab_enable && + !d->keyboard_grab_inhibit && + !d->disable_inputs) + try_keyboard_grab(display); + else + try_keyboard_ungrab(display); +} + +static void set_mouse_accel(SpiceDisplay *display, gboolean enabled) +{ + SpiceDisplayPrivate *d = display->priv; + +#if defined GDK_WINDOWING_X11 + GdkWindow *w = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); + + if (!GDK_IS_X11_DISPLAY(gdk_window_get_display(w))) { + SPICE_DEBUG("FIXME: gtk backend is not X11"); + return; + } + + Display *x_display = GDK_WINDOW_XDISPLAY(w); + if (enabled) { + /* restore mouse acceleration */ + XChangePointerControl(x_display, True, True, + d->x11_accel_numerator, d->x11_accel_denominator, d->x11_threshold); + } else { + XGetPointerControl(x_display, + &d->x11_accel_numerator, &d->x11_accel_denominator, &d->x11_threshold); + /* set mouse acceleration to default */ + XChangePointerControl(x_display, True, True, -1, -1, -1); + SPICE_DEBUG("disabled X11 mouse motion %d %d %d", + d->x11_accel_numerator, d->x11_accel_denominator, d->x11_threshold); + } +#elif defined GDK_WINDOWING_WIN32 + if (enabled) { + g_return_if_fail(SystemParametersInfo(SPI_SETMOUSE, 0, &d->win_mouse, 0)); + g_return_if_fail(SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)(INT_PTR)d->win_mouse_speed, 0)); + } else { + int accel[3] = { 0, 0, 0 }; // disabled + g_return_if_fail(SystemParametersInfo(SPI_GETMOUSE, 0, &d->win_mouse, 0)); + g_return_if_fail(SystemParametersInfo(SPI_GETMOUSESPEED, 0, &d->win_mouse_speed, 0)); + g_return_if_fail(SystemParametersInfo(SPI_SETMOUSE, 0, &accel, SPIF_SENDCHANGE)); + g_return_if_fail(SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)10, SPIF_SENDCHANGE)); // default + } +#else + g_warning("Mouse acceleration code missing for your platform"); +#endif +} + +#ifdef G_OS_WIN32 +static gboolean win32_clip_cursor(void) +{ + RECT window, workarea, rect; + HMONITOR monitor; + MONITORINFO mi = { 0, }; + + g_return_val_if_fail(win32_window != NULL, FALSE); + + if (!GetWindowRect(win32_window, &window)) + goto error; + + monitor = MonitorFromRect(&window, MONITOR_DEFAULTTONEAREST); + g_return_val_if_fail(monitor != NULL, false); + + mi.cbSize = sizeof(mi); + if (!GetMonitorInfo(monitor, &mi)) + goto error; + workarea = mi.rcWork; + + if (!IntersectRect(&rect, &window, &workarea)) { + g_critical("error clipping cursor"); + return false; + } + + SPICE_DEBUG("clip rect %ld %ld %ld %ld\n", + rect.left, rect.right, rect.top, rect.bottom); + + if (!ClipCursor(&rect)) + goto error; + + return true; + +error: + { + DWORD errval = GetLastError(); + gchar *errstr = g_win32_error_message(errval); + g_warning("failed to clip cursor (%lu) %s", errval, errstr); + } + + return false; +} +#endif + +static gboolean do_pointer_grab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + GdkWindow *window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); + GdkGrabStatus status; + GdkCursor *blank = get_blank_cursor(); + gboolean grab_successful = FALSE; + + if (!gtk_widget_get_realized(GTK_WIDGET(display))) + goto end; + +#ifdef G_OS_WIN32 + if (!win32_clip_cursor()) + goto end; +#endif + + try_keyboard_grab(display); + /* + * from gtk-vnc: + * For relative mouse to work correctly when grabbed we need to + * allow the pointer to move anywhere on the local desktop, so + * use NULL for the 'confine_to' argument. Furthermore we need + * the coords to be reported to our VNC window, regardless of + * what window the pointer is actally over, so use 'FALSE' for + * 'owner_events' parameter + */ + status = gdk_pointer_grab(window, FALSE, + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON_MOTION_MASK | + GDK_SCROLL_MASK, + NULL, + blank, + GDK_CURRENT_TIME); + grab_successful = (status == GDK_GRAB_SUCCESS); + if (!grab_successful) { + d->mouse_grab_active = false; + g_warning("pointer grab failed %u", status); + } else { + d->mouse_grab_active = true; + g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, true); + spice_gtk_session_set_pointer_grabbed(d->gtk_session, true); + set_mouse_accel(display, FALSE); + } + +end: + g_object_unref(blank); + return grab_successful; +} + +static void update_mouse_pointer(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + GdkWindow *window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display))); + + if (!window) + return; + + switch (d->mouse_mode) { + case SPICE_MOUSE_MODE_CLIENT: + if (gdk_window_get_cursor(window) != d->mouse_cursor) + gdk_window_set_cursor(window, d->mouse_cursor); + break; + case SPICE_MOUSE_MODE_SERVER: + if (gdk_window_get_cursor(window) != NULL) + gdk_window_set_cursor(window, NULL); + break; + default: + g_warn_if_reached(); + break; + } +} + +static void try_mouse_grab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + if (g_getenv("SPICE_NOGRAB")) + return; + if (d->disable_inputs) + return; + + if (!d->mouse_have_pointer) + return; + if (!d->keyboard_have_focus) + return; + + if (!d->mouse_grab_enable) + return; + if (d->mouse_mode != SPICE_MOUSE_MODE_SERVER) + return; + if (d->mouse_grab_active) + return; + + if (!do_pointer_grab(display)) + return; + + d->mouse_last_x = -1; + d->mouse_last_y = -1; +} + +static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion) +{ + SpiceDisplayPrivate *d = display->priv; + gint xr, yr; + +#ifdef G_OS_WIN32 + RECT clip; + g_return_if_fail(GetClipCursor(&clip)); + xr = clip.left + (clip.right - clip.left) / 2; + yr = clip.top + (clip.bottom - clip.top) / 2; + /* the clip rectangle has no offset, so we can't use gdk_wrap_pointer */ + SetCursorPos(xr, yr); + d->mouse_last_x = -1; + d->mouse_last_y = -1; +#else + GdkScreen *screen = gtk_widget_get_screen(GTK_WIDGET(display)); + xr = gdk_screen_get_width(screen) / 2; + yr = gdk_screen_get_height(screen) / 2; + + if (xr != (gint)motion->x_root || yr != (gint)motion->y_root) { + /* FIXME: we try our best to ignore that next pointer move event.. */ + gdk_display_sync(gdk_screen_get_display(screen)); + + gdk_display_warp_pointer(gtk_widget_get_display(GTK_WIDGET(display)), + screen, xr, yr); + d->mouse_last_x = -1; + d->mouse_last_y = -1; + } +#endif + +} + +static void try_mouse_ungrab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + double s; + int x, y; + + if (!d->mouse_grab_active) + return; + + gdk_pointer_ungrab(GDK_CURRENT_TIME); + gtk_grab_remove(GTK_WIDGET(display)); +#ifdef G_OS_WIN32 + ClipCursor(NULL); +#endif + set_mouse_accel(display, TRUE); + + d->mouse_grab_active = false; + + spice_display_get_scaling(display, &s, &x, &y, NULL, NULL); + + gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(display)), + x + d->mouse_guest_x * s, + y + d->mouse_guest_y * s, + &x, &y); + + gdk_display_warp_pointer(gtk_widget_get_display(GTK_WIDGET(display)), + gtk_widget_get_screen(GTK_WIDGET(display)), + x, y); + + g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, false); + spice_gtk_session_set_pointer_grabbed(d->gtk_session, false); +} + +static void update_mouse_grab(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + if (d->mouse_grab_enable && + !d->keyboard_grab_inhibit && + !d->disable_inputs) + try_mouse_grab(display); + else + try_mouse_ungrab(display); +} + +static void recalc_geometry(GtkWidget *widget) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + gdouble zoom = 1.0; + + if (spice_cairo_is_scaled(display)) + zoom = (gdouble)d->zoom_level / 100; + + SPICE_DEBUG("recalc geom monitor: %d:%d, guest +%d+%d:%dx%d, window %dx%d, zoom %g", + d->channel_id, d->monitor_id, d->area.x, d->area.y, d->area.width, d->area.height, + d->ww, d->wh, zoom); + + if (d->resize_guest_enable) + spice_main_set_display(d->main, get_display_id(display), + d->area.x, d->area.y, d->ww / zoom, d->wh / zoom); +} + +/* ---------------------------------------------------------------- */ + +#define CONVERT_0565_TO_0888(s) \ + (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ + ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) + +#define CONVERT_0565_TO_8888(s) (CONVERT_0565_TO_0888(s) | 0xff000000) + +#define CONVERT_0555_TO_0888(s) \ + (((((s) & 0x001f) << 3) | (((s) & 0x001c) >> 2)) | \ + ((((s) & 0x03e0) << 6) | (((s) & 0x0380) << 1)) | \ + ((((s) & 0x7c00) << 9) | ((((s) & 0x7000)) << 4))) + +#define CONVERT_0555_TO_8888(s) (CONVERT_0555_TO_0888(s) | 0xff000000) + +static gboolean do_color_convert(SpiceDisplay *display, GdkRectangle *r) +{ + SpiceDisplayPrivate *d = display->priv; + guint32 *dest = d->canvas.data; + guint16 *src = d->canvas.data_origin; + gint x, y; + + g_return_val_if_fail(r != NULL, false); + g_return_val_if_fail(d->canvas.format == SPICE_SURFACE_FMT_16_555 || + d->canvas.format == SPICE_SURFACE_FMT_16_565, false); + + src += (d->canvas.stride / 2) * r->y + r->x; + dest += d->area.width * (r->y - d->area.y) + (r->x - d->area.x); + + if (d->canvas.format == SPICE_SURFACE_FMT_16_555) { + for (y = 0; y < r->height; y++) { + for (x = 0; x < r->width; x++) { + dest[x] = CONVERT_0555_TO_0888(src[x]); + } + + dest += d->area.width; + src += d->canvas.stride / 2; + } + } else if (d->canvas.format == SPICE_SURFACE_FMT_16_565) { + for (y = 0; y < r->height; y++) { + for (x = 0; x < r->width; x++) { + dest[x] = CONVERT_0565_TO_0888(src[x]); + } + + dest += d->area.width; + src += d->canvas.stride / 2; + } + } + + return true; +} + +#ifndef G_OS_WIN32 +static void set_egl_enabled(SpiceDisplay *display, bool enabled) +{ + SpiceDisplayPrivate *d = display->priv; + GtkWidget *area; + + if (egl_enabled(d) == enabled) + return; + +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + /* even though the function is marked as deprecated, it's the + * only way I found to prevent glitches when the window is + * resized. */ + area = gtk_stack_get_child_by_name(d->stack, "draw-area"); + gtk_widget_set_double_buffered(GTK_WIDGET(area), !enabled); + } else +#endif + { + area = gtk_stack_get_child_by_name(d->stack, "gl-area"); + gtk_stack_set_visible_child_name(d->stack, + enabled ? "gl-area" : "draw-area"); + } + + if (enabled) { + spice_egl_resize_display(display, d->ww, d->wh); + } + + d->egl.enabled = enabled; +} +#endif + +static gboolean draw_event(GtkWidget *widget, cairo_t *cr, gpointer data) +{ + SpiceDisplay *display = SPICE_DISPLAY(data); + SpiceDisplayPrivate *d = display->priv; + g_return_val_if_fail(d != NULL, false); + +#ifndef G_OS_WIN32 + if (egl_enabled(d) && + g_str_equal(gtk_stack_get_visible_child_name(d->stack), "draw-area")) { + spice_egl_update_display(display); + return false; + } +#endif + + if (d->mark == 0 || d->canvas.data == NULL || + d->area.width == 0 || d->area.height == 0) + return false; + + spice_cairo_draw_event(display, cr); + update_mouse_pointer(display); + + return true; +} + +/* ---------------------------------------------------------------- */ +typedef enum { + SEND_KEY_PRESS, + SEND_KEY_RELEASE, +} SendKeyType; + +static void key_press_and_release(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + if (d->key_delayed_scancode == 0) + return; + + spice_inputs_key_press_and_release(d->inputs, d->key_delayed_scancode); + d->key_delayed_scancode = 0; + + if (d->key_delayed_id) { + g_source_remove(d->key_delayed_id); + d->key_delayed_id = 0; + } +} + +static gboolean key_press_delayed(gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + + if (d->key_delayed_scancode == 0) + return FALSE; + + spice_inputs_key_press(d->inputs, d->key_delayed_scancode); + d->key_delayed_scancode = 0; + + if (d->key_delayed_id) { + g_source_remove(d->key_delayed_id); + d->key_delayed_id = 0; + } + + return FALSE; +} + +static void send_key(SpiceDisplay *display, int scancode, SendKeyType type, gboolean press_delayed) +{ + SpiceDisplayPrivate *d = display->priv; + uint32_t i, b, m; + + g_return_if_fail(scancode != 0); + + if (!d->inputs) + return; + + if (d->disable_inputs) + return; + + i = scancode / 32; + b = scancode % 32; + m = (1 << b); + g_return_if_fail(i < SPICE_N_ELEMENTS(d->key_state)); + + switch (type) { + case SEND_KEY_PRESS: + /* ensure delayed key is pressed before any new input event */ + key_press_delayed(display); + + if (press_delayed && + d->keypress_delay != 0 && + !(d->key_state[i] & m)) { + g_warn_if_fail(d->key_delayed_id == 0); + d->key_delayed_id = g_timeout_add(d->keypress_delay, key_press_delayed, display); + d->key_delayed_scancode = scancode; + } else + spice_inputs_key_press(d->inputs, scancode); + + d->key_state[i] |= m; + break; + + case SEND_KEY_RELEASE: + if (!(d->key_state[i] & m)) + break; + + if (d->key_delayed_scancode == scancode) + key_press_and_release(display); + else { + /* ensure delayed key is pressed before other key are released */ + key_press_delayed(display); + spice_inputs_key_release(d->inputs, scancode); + } + + d->key_state[i] &= ~m; + break; + + default: + g_warn_if_reached(); + } +} + +static void release_keys(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + uint32_t i, b; + + SPICE_DEBUG("%s", __FUNCTION__); + for (i = 0; i < SPICE_N_ELEMENTS(d->key_state); i++) { + if (!d->key_state[i]) { + continue; + } + for (b = 0; b < 32; b++) { + unsigned int scancode = i * 32 + b; + if (scancode != 0) { + send_key(display, scancode, SEND_KEY_RELEASE, FALSE); + } + } + } +} + +static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval, + int check_type, int reset_type) +{ + SpiceDisplayPrivate *d = display->priv; + int i; + + if (!d->grabseq->nkeysyms) + return FALSE; + + if (type == check_type) { + /* Record the new key */ + for (i = 0 ; i < d->grabseq->nkeysyms ; i++) + if (d->grabseq->keysyms[i] == keyval) + d->activeseq[i] = TRUE; + + /* Return if any key is missing */ + for (i = 0 ; i < d->grabseq->nkeysyms ; i++) + if (d->activeseq[i] == FALSE) + return FALSE; + + /* resets the whole grab sequence on success */ + memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms); + return TRUE; + } else if (type == reset_type) { + /* reset key event type resets the whole grab sequence */ + memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms); + d->seq_pressed = FALSE; + return FALSE; + } else + g_warn_if_reached(); + + return FALSE; +} + +static gboolean check_for_grab_key_pressed(SpiceDisplay *display, int type, int keyval) +{ + return check_for_grab_key(display, type, keyval, GDK_KEY_PRESS, GDK_KEY_RELEASE); +} + +static gboolean check_for_grab_key_released(SpiceDisplay *display, int type, int keyval) +{ + return check_for_grab_key(display, type, keyval, GDK_KEY_RELEASE, GDK_KEY_PRESS); +} + +static void update_display(SpiceDisplay *display) +{ +#ifdef G_OS_WIN32 + win32_window = display ? GDK_WINDOW_HWND(gtk_widget_get_window(GTK_WIDGET(display))) : NULL; +#endif +} + +static gboolean key_event(GtkWidget *widget, GdkEventKey *key) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + int scancode = 0; +#ifdef G_OS_WIN32 + int native_scancode; + WORD langid = LOWORD(GetKeyboardLayout(0)); + gboolean no_key_release = FALSE; +#endif + +#ifdef G_OS_WIN32 + /* Try to get scancode with gdk_event_get_scancode. + * This API is available from 3.22 or if backported. + */ +#if HAVE_GDK_EVENT_GET_SCANCODE + native_scancode = gdk_event_get_scancode((GdkEvent *) key); + if (native_scancode) { + scancode = native_scancode & 0x1ff; + /* Windows always set extended attribute for these keys */ + if (scancode == (0x100|DIK_NUMLOCK) || scancode == (0x100|DIK_RSHIFT)) + scancode &= 0xff; + } +#else + native_scancode = 0; +#endif + + /* on windows, we ought to ignore the reserved key event? */ + if (!native_scancode && key->hardware_keycode == 0xff) + return false; + + if (!d->keyboard_grab_active) { + if (key->hardware_keycode == VK_LWIN || + key->hardware_keycode == VK_RWIN || + key->hardware_keycode == VK_APPS) + return false; + } + +#endif + SPICE_DEBUG("%s %s: keycode: %d state: %u group %d modifier %d", + __FUNCTION__, key->type == GDK_KEY_PRESS ? "press" : "release", + key->hardware_keycode, key->state, key->group, key->is_modifier); + + if (!d->seq_pressed && check_for_grab_key_pressed(display, key->type, key->keyval)) { + g_signal_emit(widget, signals[SPICE_DISPLAY_GRAB_KEY_PRESSED], 0); + + if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) { + if (d->mouse_grab_active) + try_mouse_ungrab(display); + else + try_mouse_grab(display); + } + d->seq_pressed = TRUE; + } else if (d->seq_pressed && check_for_grab_key_released(display, key->type, key->keyval)) { + release_keys(display); + if (!d->keyboard_grab_released) { + d->keyboard_grab_released = TRUE; + try_keyboard_ungrab(display); + } else { + d->keyboard_grab_released = FALSE; + try_keyboard_grab(display); + } + d->seq_pressed = FALSE; + } + + if (!d->inputs) + return true; + + if (!scancode) + scancode = vnc_display_keymap_gdk2xtkbd(d->keycode_map, d->keycode_maplen, + key->hardware_keycode); +#ifdef G_OS_WIN32 + if (!native_scancode) { + native_scancode = MapVirtualKey(key->hardware_keycode, MAPVK_VK_TO_VSC); + /* MapVirtualKey doesn't return scancode with needed higher byte */ + scancode = native_scancode | (scancode & 0xff00); + } + + /* Some virtual-key codes are missed in MapVirtualKey(). */ + switch (langid) { + case MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN): + if (native_scancode == 0) { + switch (key->hardware_keycode) { + case VK_DBE_DBCSCHAR: /* from Pressed Zenkaku_Hankaku */ + case VK_KANJI: /* from Alt + Zenkaku_Hankaku */ + case VK_DBE_ENTERIMECONFIGMODE: + /* from Ctrl+Alt+Zenkaku_Hankaku */ + scancode = MapVirtualKey(VK_DBE_SBCSCHAR, MAPVK_VK_TO_VSC); + /* to Released Zenkaku_Hankaku */ + break; + case VK_CAPITAL: /* from Shift + Eisu_toggle */ + case VK_DBE_CODEINPUT: /* from Pressed Ctrl+Alt+Eisu_toggle */ + case VK_DBE_NOCODEINPUT: /* from Released Ctrl+Alt+Eisu_toggle */ + scancode = MapVirtualKey(VK_DBE_ALPHANUMERIC, MAPVK_VK_TO_VSC); + /* to Eisu_toggle */ + break; + case VK_DBE_ROMAN: /* from Pressed Alt+Hiragana_Katakana */ + case VK_KANA: /* from Ctrl+Shift+Hiragana_Katakana */ + scancode = MapVirtualKey(VK_DBE_HIRAGANA, MAPVK_VK_TO_VSC); + /* to Hiragana_Katakana */ + break; + case VK_DBE_ENTERWORDREGISTERMODE: + /* from Ctrl + Alt + Muhenkan */ + scancode = MapVirtualKey(VK_NONCONVERT, MAPVK_VK_TO_VSC); + /* to Muhenkan */ + break; + } + } + break; + case MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN): + if (key->hardware_keycode == VK_HANGUL && native_scancode == DIK_LALT) { + /* Left Alt (VK_MENU) has the scancode DIK_LALT (0x38) but + * Hangul (VK_HANGUL) has the scancode 0x138 + */ + scancode = native_scancode | 0x100; + } + break; + } + + /* Emulate KeyRelease events for the following keys. + * + * Alt+Zenkaku_Hankaku generates WM_KEYDOWN VK_KANJI and no WM_KEYUP + * and it caused unlimited VK_KANJI in Linux desktop and the desktop + * hung up. We send WM_KEYUP VK_KANJI here to avoid unlimited events. + * + * Eisu_toggle generates WM_KEYDOWN VK_DBE_ALPHANUMERIC only in + * English mode, WM_KEYDOWN VK_DBE_ALPHANUMERIC and WM_KEYUP + * VK_DBE_HIRAGANA in Japanese mode, and it caused unlimited + * VK_DBE_ALPHANUMERIC in Linux desktop. + * Since VK_DBE_HIRAGANA is also assigned in Hiragana key, + * we send WM_KEYUP VK_DBE_ALPHANUMERIC here to avoid unlimited events. + * No KeyPress VK_DBE_HIRAGANA seems harmless. + * + * Hiragana_Katakana generates WM_KEYDOWN VK_DBE_HIRAGANA and + * WM_KEYUP VK_DBE_ALPHANUMERIC in English mode, WM_KEYDOWN + * VK_DBE_HIRAGANA only in Japanese mode, and it caused unlimited + * VK_DBE_HIRAGANA in Linux desktop. + * + * Alt+Hiragana_Katakana generates WM_KEYUP VK_DBE_NOROMAN and + * WM_KEYDOWN VK_DBE_ROMAN but the KeyRelease is called before + * KeyDown is called and it caused unlimited VK_DBE_ROMAN. + * We ignore the scancode of VK_DBE_NOROMAN and emulate WM_KEYUP + * VK_DBE_ROMAN. + * + * Ctrl+Alt+Zenkaku_Hankaku generates WM_KEYDOWN VK_DBE_ENTERIMECONFIGMODE + * and no WM_KEYUP and it caused unlimited VK_DBE_ENTERIMECONFIGMODE + * in Linux desktop. + */ + switch (langid) { + case MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN): + switch (key->hardware_keycode) { + case VK_KANJI: /* Alt + Zenkaku_Hankaku */ + case VK_DBE_ALPHANUMERIC: /* Eisu_toggle */ + case VK_DBE_HIRAGANA: /* Hiragana_Katakana */ + case VK_DBE_ROMAN: /* Alt+Hiragana_Katakana */ + case VK_DBE_ENTERIMECONFIGMODE: /* Ctrl + Alt + Zenkaku_Hankaku */ + no_key_release = TRUE; + break; + } + break; + } +#endif + + switch (key->type) { + case GDK_KEY_PRESS: + send_key(display, scancode, SEND_KEY_PRESS, !key->is_modifier); +#ifdef G_OS_WIN32 + if (no_key_release) + send_key(display, scancode, SEND_KEY_RELEASE, !key->is_modifier); +#endif + break; + case GDK_KEY_RELEASE: + send_key(display, scancode, SEND_KEY_RELEASE, !key->is_modifier); + break; + default: + g_warn_if_reached(); + break; + } + + return true; +} + +static guint get_scancode_from_keyval(SpiceDisplay *display, guint keyval) +{ + SpiceDisplayPrivate *d = display->priv; + guint keycode = 0; + GdkKeymapKey *keys = NULL; + gint n_keys = 0; + + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), + keyval, &keys, &n_keys)) { + /* FIXME what about levels? */ + keycode = keys[0].keycode; + g_free(keys); + } else { + g_warning("could not lookup keyval %u, please report a bug", keyval); + return 0; + } + + return vnc_display_keymap_gdk2xtkbd(d->keycode_map, d->keycode_maplen, keycode); +} + + +/** + * spice_display_send_keys: + * @display: The #SpiceDisplay + * @keyvals: (array length=nkeyvals): Keyval array + * @nkeyvals: Length of keyvals + * @kind: #SpiceDisplayKeyEvent action + * + * Send keyval press/release events to the display. + * + **/ +void spice_display_send_keys(SpiceDisplay *display, const guint *keyvals, + int nkeyvals, SpiceDisplayKeyEvent kind) +{ + int i; + + g_return_if_fail(SPICE_IS_DISPLAY(display)); + g_return_if_fail(keyvals != NULL); + + SPICE_DEBUG("%s", __FUNCTION__); + + if (kind & SPICE_DISPLAY_KEY_EVENT_PRESS) { + for (i = 0 ; i < nkeyvals ; i++) + send_key(display, get_scancode_from_keyval(display, keyvals[i]), SEND_KEY_PRESS, FALSE); + } + + if (kind & SPICE_DISPLAY_KEY_EVENT_RELEASE) { + for (i = (nkeyvals-1) ; i >= 0 ; i--) + send_key(display, get_scancode_from_keyval(display, keyvals[i]), SEND_KEY_RELEASE, FALSE); + } +} + +static gboolean enter_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC_UNUSED) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + d->mouse_have_pointer = true; + spice_gtk_session_set_mouse_has_pointer(d->gtk_session, true); + try_keyboard_grab(display); + update_display(display); + + return true; +} + +static gboolean leave_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC_UNUSED) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + if (d->mouse_grab_active) + return true; + + d->mouse_have_pointer = false; + spice_gtk_session_set_mouse_has_pointer(d->gtk_session, false); + try_keyboard_ungrab(display); + + return true; +} + +static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + /* + * Ignore focus in when we already have the focus + * (this happens when doing an ungrab from the leave_event callback). + */ + if (d->keyboard_have_focus) + return true; + + release_keys(display); +#ifdef G_OS_WIN32 + /* Reset the IME context of the focused window. + * Note that the focused window can be different from SpiceDisplay + * one but the events are received and forwarder by this window. */ + HWND hwnd_focused = GetFocus(); + if (hwnd_focused != NULL) { + ImmAssociateContext(hwnd_focused, NULL); + } +#endif + if (!d->disable_inputs) + spice_gtk_session_sync_keyboard_modifiers(d->gtk_session); + if (d->keyboard_grab_released) + memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms); + update_keyboard_focus(display, true); + try_keyboard_grab(display); + + if (gtk_widget_get_realized(widget)) + update_display(display); + + return true; +} + +static gboolean focus_out_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + update_display(NULL); + + /* + * Ignore focus out after a keyboard grab + * (this happens when doing the grab from the enter_event callback). + */ + if (d->keyboard_grab_active) + return true; + + release_keys(display); + update_keyboard_focus(display, false); + + return true; +} + +static int button_gdk_to_spice(guint gdk) +{ + static const int map[] = { + [ 1 ] = SPICE_MOUSE_BUTTON_LEFT, + [ 2 ] = SPICE_MOUSE_BUTTON_MIDDLE, + [ 3 ] = SPICE_MOUSE_BUTTON_RIGHT, + [ 4 ] = SPICE_MOUSE_BUTTON_UP, + [ 5 ] = SPICE_MOUSE_BUTTON_DOWN, + }; + + if (gdk < SPICE_N_ELEMENTS(map)) { + return map [ gdk ]; + } + return 0; +} + +static int button_mask_gdk_to_spice(int gdk) +{ + int spice = 0; + + if (gdk & GDK_BUTTON1_MASK) + spice |= SPICE_MOUSE_BUTTON_MASK_LEFT; + if (gdk & GDK_BUTTON2_MASK) + spice |= SPICE_MOUSE_BUTTON_MASK_MIDDLE; + if (gdk & GDK_BUTTON3_MASK) + spice |= SPICE_MOUSE_BUTTON_MASK_RIGHT; + return spice; +} + +static void transform_input(SpiceDisplay *display, + double window_x, double window_y, + int *input_x, int *input_y) +{ + SpiceDisplayPrivate *d = display->priv; + int display_x, display_y, display_w, display_h; + double is; + + spice_display_get_scaling(display, NULL, + &display_x, &display_y, + &display_w, &display_h); + + /* For input we need a different scaling factor in order to + be able to reach the full width of a display. For instance, consider + a display of 100 pixels showing in a window 10 pixels wide. The normal + scaling factor here would be 100/10==10, but if you then take the largest + possible window coordinate, i.e. 9 and multiply by 10 you get 90, not 99, + which is the max display coord. + + If you want to be able to reach the last pixel in the window you need + max_window_x * input_scale == max_display_x, which is + (window_width - 1) * input_scale == (display_width - 1) + + Note, this is the inverse of s (i.e. s ~= 1/is) as we're converting the + coordinates in the inverse direction (window -> display) as the fb size + (display -> window). + */ + is = (double)(d->area.width-1) / (double)(display_w-1); + + window_x -= display_x; + window_y -= display_y; + + *input_x = floor (window_x * is); + *input_y = floor (window_y * is); +} + +static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + int x, y; + + if (!d->inputs) + return true; + if (d->disable_inputs) + return true; + + d->seq_pressed = FALSE; + + if (d->keyboard_grab_released && d->keyboard_have_focus) { + d->keyboard_grab_released = FALSE; + release_keys(display); + try_keyboard_grab(display); + } + + transform_input(display, motion->x, motion->y, &x, &y); + + switch (d->mouse_mode) { + case SPICE_MOUSE_MODE_CLIENT: + if (x >= 0 && x < d->area.width && + y >= 0 && y < d->area.height) { + spice_inputs_position(d->inputs, x, y, get_display_id(display), + button_mask_gdk_to_spice(motion->state)); + } + break; + case SPICE_MOUSE_MODE_SERVER: + if (d->mouse_grab_active) { + gint dx = d->mouse_last_x != -1 ? x - d->mouse_last_x : 0; + gint dy = d->mouse_last_y != -1 ? y - d->mouse_last_y : 0; + + spice_inputs_motion(d->inputs, dx, dy, + button_mask_gdk_to_spice(motion->state)); + + d->mouse_last_x = x; + d->mouse_last_y = y; + if (dx != 0 || dy != 0) + mouse_wrap(display, motion); + } + break; + default: + g_warn_if_reached(); + break; + } + return true; +} + +static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *scroll) +{ + int button; + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + if (!d->inputs) + return true; + if (d->disable_inputs) + return true; + + if (scroll->direction == GDK_SCROLL_UP) + button = SPICE_MOUSE_BUTTON_UP; + else if (scroll->direction == GDK_SCROLL_DOWN) + button = SPICE_MOUSE_BUTTON_DOWN; + else { + SPICE_DEBUG("unsupported scroll direction"); + return true; + } + + spice_inputs_button_press(d->inputs, button, + button_mask_gdk_to_spice(scroll->state)); + spice_inputs_button_release(d->inputs, button, + button_mask_gdk_to_spice(scroll->state)); + return true; +} + +static gboolean button_event(GtkWidget *widget, GdkEventButton *button) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + int x, y; + + SPICE_DEBUG("%s %s: button %u, state 0x%x", __FUNCTION__, + button->type == GDK_BUTTON_PRESS ? "press" : "release", + button->button, button->state); + + if (d->disable_inputs) + return true; + + transform_input(display, button->x, button->y, &x, &y); + if ((x < 0 || x >= d->area.width || + y < 0 || y >= d->area.height) && + d->mouse_mode == SPICE_MOUSE_MODE_CLIENT) { + /* rule out clicks in outside region */ + return true; + } + + gtk_widget_grab_focus(widget); + if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) { + if (!d->mouse_grab_active) { + try_mouse_grab(display); + return true; + } + } else + /* allow to drag and drop between windows/displays: + + By default, X (and other window system) do a pointer grab + when you press a button, so that the release event is + received by the same window regardless of where the pointer + is. Here, we change that behaviour, so that you can press + and release in two differents displays. This is only + supported in client mouse mode. + + FIXME: should be multiple widget grab, but how? + or should know the position of the other widgets? + */ + gdk_pointer_ungrab(GDK_CURRENT_TIME); + + if (!d->inputs) + return true; + + switch (button->type) { + case GDK_BUTTON_PRESS: + spice_inputs_button_press(d->inputs, + button_gdk_to_spice(button->button), + button_mask_gdk_to_spice(button->state)); + break; + case GDK_BUTTON_RELEASE: + spice_inputs_button_release(d->inputs, + button_gdk_to_spice(button->button), + button_mask_gdk_to_spice(button->state)); + break; + default: + break; + } + return true; +} + +static void size_allocate(GtkWidget *widget, GtkAllocation *conf, gpointer data) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + if (conf->width == d->ww && conf->height == d->wh && + conf->x == d->mx && conf->y == d->my) { + return; + } + + if (conf->width != d->ww || conf->height != d->wh) { + d->ww = conf->width; + d->wh = conf->height; + recalc_geometry(widget); +#ifndef G_OS_WIN32 + if (egl_enabled(d)) + spice_egl_resize_display(display, conf->width, conf->height); +#endif + } + + d->mx = conf->x; + d->my = conf->y; + +#ifdef G_OS_WIN32 + if (d->mouse_grab_active) { + try_mouse_ungrab(display); + try_mouse_grab(display); + } +#endif +} + +static void update_image(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + spice_cairo_image_create(display); + if (d->canvas.convert) + do_color_convert(display, &d->area); +} + +static void realize(GtkWidget *widget) +{ + SpiceDisplay *display = SPICE_DISPLAY(widget); + SpiceDisplayPrivate *d = display->priv; + + GTK_WIDGET_CLASS(spice_display_parent_class)->realize(widget); + + d->keycode_map = + vnc_display_keymap_gdk2xtkbd_table(gtk_widget_get_window(widget), + &d->keycode_maplen); + + update_image(display); +} + +static void unrealize(GtkWidget *widget) +{ + spice_cairo_image_destroy(SPICE_DISPLAY(widget)); +#ifndef G_OS_WIN32 + spice_egl_unrealize_display(SPICE_DISPLAY(widget)); +#endif + + GTK_WIDGET_CLASS(spice_display_parent_class)->unrealize(widget); +} + + +/* ---------------------------------------------------------------- */ + +static void spice_display_class_init(SpiceDisplayClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS(klass); + + gtkwidget_class->key_press_event = key_event; + gtkwidget_class->key_release_event = key_event; + gtkwidget_class->enter_notify_event = enter_event; + gtkwidget_class->leave_notify_event = leave_event; + gtkwidget_class->focus_in_event = focus_in_event; + gtkwidget_class->focus_out_event = focus_out_event; + gtkwidget_class->motion_notify_event = motion_event; + gtkwidget_class->button_press_event = button_event; + gtkwidget_class->button_release_event = button_event; + gtkwidget_class->scroll_event = scroll_event; + gtkwidget_class->realize = realize; + gtkwidget_class->unrealize = unrealize; + + gobject_class->constructor = spice_display_constructor; + gobject_class->dispose = spice_display_dispose; + gobject_class->finalize = spice_display_finalize; + gobject_class->get_property = spice_display_get_property; + gobject_class->set_property = spice_display_set_property; + + /** + * SpiceDisplay:session: + * + * #SpiceSession for this #SpiceDisplay + * + **/ + g_object_class_install_property + (gobject_class, PROP_SESSION, + g_param_spec_object("session", + "Session", + "SpiceSession", + SPICE_TYPE_SESSION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:channel-id: + * + * channel-id for this #SpiceDisplay + * + **/ + g_object_class_install_property + (gobject_class, PROP_CHANNEL_ID, + g_param_spec_int("channel-id", + "Channel ID", + "Channel ID for this display", + 0, 255, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_KEYBOARD_GRAB, + g_param_spec_boolean("grab-keyboard", + "Grab Keyboard", + "Whether we should grab the keyboard.", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_MOUSE_GRAB, + g_param_spec_boolean("grab-mouse", + "Grab Mouse", + "Whether we should grab the mouse.", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_RESIZE_GUEST, + g_param_spec_boolean("resize-guest", + "Resize guest", + "Try to adapt guest display on window resize. " + "Requires guest cooperation.", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:ready: + * + * Indicate whether the display is ready to be shown. It takes + * into account several conditions, such as the channel display + * "mark" state, whether the monitor area is visible.. + * + * Since: 0.13 + **/ + g_object_class_install_property + (gobject_class, PROP_READY, + g_param_spec_boolean("ready", + "Ready", + "Ready to display", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (gobject_class, PROP_SCALING, + g_param_spec_boolean("scaling", "Scaling", + "Whether we should use scaling", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:only-downscale: + * + * If scaling, only scale down, never up. + * + * Since: 0.14 + **/ + g_object_class_install_property + (gobject_class, PROP_ONLY_DOWNSCALE, + g_param_spec_boolean("only-downscale", "Only Downscale", + "If scaling, only scale down, never up", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:keypress-delay: + * + * Delay in ms of non-modifiers key press events. If the key is + * released before this delay, a single press & release event is + * sent to the server. If the key is pressed longer than the + * keypress-delay, the server will receive the delayed press + * event, and a following release event when the key is released. + * + * Since: 0.13 + **/ + g_object_class_install_property + (gobject_class, PROP_KEYPRESS_DELAY, + g_param_spec_uint("keypress-delay", "Keypress delay", + "Keypress delay", + 0, G_MAXUINT, 100, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:disable-inputs: + * + * Disable all keyboard & mouse inputs. + * + * Since: 0.8 + **/ + g_object_class_install_property + (gobject_class, PROP_DISABLE_INPUTS, + g_param_spec_boolean("disable-inputs", "Disable inputs", + "Whether inputs should be disabled", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + + /** + * SpiceDisplay:zoom-level: + * + * Zoom level in percentage, from 10 to 400. Default to 100. + * (this option is only supported with cairo backend when scaling + * is enabled) + * + * Since: 0.10 + **/ + g_object_class_install_property + (gobject_class, PROP_ZOOM_LEVEL, + g_param_spec_int("zoom-level", "Zoom Level", + "Zoom Level", + 10, 400, 100, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay:monitor-id: + * + * Select monitor from #SpiceDisplay to show. + * The value -1 means the whole display is shown. + * By default, the monitor 0 is selected. + * + * Since: 0.13 + **/ + g_object_class_install_property + (gobject_class, PROP_MONITOR_ID, + g_param_spec_int("monitor-id", + "Monitor ID", + "Select monitor ID", + -1, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceDisplay::mouse-grab: + * @display: the #SpiceDisplay that emitted the signal + * @status: 1 if grabbed, 0 otherwise. + * + * Notify when the mouse grab is active or not. + **/ + signals[SPICE_DISPLAY_MOUSE_GRAB] = + g_signal_new("mouse-grab", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayClass, mouse_grab), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + + /** + * SpiceDisplay::keyboard-grab: + * @display: the #SpiceDisplay that emitted the signal + * @status: 1 if grabbed, 0 otherwise. + * + * Notify when the keyboard grab is active or not. + **/ + signals[SPICE_DISPLAY_KEYBOARD_GRAB] = + g_signal_new("keyboard-grab", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayClass, keyboard_grab), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + + /** + * SpiceDisplay::grab-keys-pressed: + * @display: the #SpiceDisplay that emitted the signal + * + * Notify when the grab keys have been pressed + **/ + signals[SPICE_DISPLAY_GRAB_KEY_PRESSED] = + g_signal_new("grab-keys-pressed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceDisplayClass, keyboard_grab), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private(klass, sizeof(SpiceDisplayPrivate)); +} + +/* ---------------------------------------------------------------- */ + +#define SPICE_GDK_BUTTONS_MASK \ + (GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK|GDK_BUTTON4_MASK|GDK_BUTTON5_MASK) + +static void update_mouse_mode(SpiceChannel *channel, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(display)); + + g_object_get(channel, "mouse-mode", &d->mouse_mode, NULL); + SPICE_DEBUG("mouse mode %u", d->mouse_mode); + + switch (d->mouse_mode) { + case SPICE_MOUSE_MODE_CLIENT: + try_mouse_ungrab(display); + break; + case SPICE_MOUSE_MODE_SERVER: + d->mouse_guest_x = -1; + d->mouse_guest_y = -1; + + if (window != NULL) { + GdkModifierType modifiers; + gdk_window_get_pointer(window, NULL, NULL, &modifiers); + + if (modifiers & SPICE_GDK_BUTTONS_MASK) + try_mouse_grab(display); + } + break; + default: + g_warn_if_reached(); + } + + update_mouse_pointer(display); +} + +static void update_area(SpiceDisplay *display, + gint x, gint y, gint width, gint height) +{ + SpiceDisplayPrivate *d = display->priv; + GdkRectangle primary; + + SPICE_DEBUG("update area +%d+%d %dx%d", x, y, width, height); + d->area = (GdkRectangle) { + .x = x, + .y = y, + .width = width, + .height = height + }; + +#ifndef G_OS_WIN32 + if (egl_enabled(d)) { + const SpiceGlScanout *so = + spice_display_get_gl_scanout(SPICE_DISPLAY_CHANNEL(d->display)); + g_return_if_fail(so != NULL); + primary = (GdkRectangle) { + .width = so->width, + .height = so->height + }; + } else +#endif + { + primary = (GdkRectangle) { + .width = d->canvas.width, + .height = d->canvas.height + }; + } + + SPICE_DEBUG("primary: %dx%d", primary.width, primary.height); + if (!gdk_rectangle_intersect(&primary, &d->area, &d->area)) { + SPICE_DEBUG("The monitor area is not intersecting primary surface"); + memset(&d->area, '\0', sizeof(d->area)); + set_monitor_ready(display, false); + return; + } + + if (!egl_enabled(d)) { + spice_cairo_image_destroy(display); + if (gtk_widget_get_realized(GTK_WIDGET(display))) + update_image(display); + } + + update_size_request(display); + + set_monitor_ready(display, true); +} + +static void primary_create(SpiceChannel *channel, gint format, + gint width, gint height, gint stride, + gint shmid, gpointer imgdata, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + + d->canvas.format = format; + d->canvas.stride = stride; + d->canvas.width = width; + d->canvas.height = height; + d->canvas.data_origin = d->canvas.data = imgdata; + + spice_display_widget_update_monitor_area(display); +} + +static void primary_destroy(SpiceChannel *channel, gpointer data) +{ + SpiceDisplay *display = SPICE_DISPLAY(data); + SpiceDisplayPrivate *d = display->priv; + + spice_cairo_image_destroy(display); + d->canvas.width = 0; + d->canvas.height = 0; + d->canvas.stride = 0; + d->canvas.data = NULL; + d->canvas.data_origin = NULL; + set_monitor_ready(display, false); +} + +static void queue_draw_area(SpiceDisplay *display, gint x, gint y, + gint width, gint height) +{ + if (!gtk_widget_get_has_window(GTK_WIDGET(display))) { + GtkAllocation allocation; + + gtk_widget_get_allocation(GTK_WIDGET(display), &allocation); + x += allocation.x; + y += allocation.y; + } + + gtk_widget_queue_draw_area(GTK_WIDGET(display), + x, y, width, height); +} + +static void invalidate(SpiceChannel *channel, + gint x, gint y, gint w, gint h, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + int display_x, display_y; + int x1, y1, x2, y2; + double s; + GdkRectangle rect = { + .x = x, + .y = y, + .width = w, + .height = h + }; + +#ifndef G_OS_WIN32 + set_egl_enabled(display, false); +#endif + + if (!gtk_widget_get_window(GTK_WIDGET(display))) + return; + + if (!gdk_rectangle_intersect(&rect, &d->area, &rect)) + return; + + if (d->canvas.convert) + do_color_convert(display, &rect); + + spice_display_get_scaling(display, &s, + &display_x, &display_y, + NULL, NULL); + + x1 = floor ((rect.x - d->area.x) * s); + y1 = floor ((rect.y - d->area.y) * s); + x2 = ceil ((rect.x - d->area.x + rect.width) * s); + y2 = ceil ((rect.y - d->area.y + rect.height) * s); + + queue_draw_area(display, + display_x + x1, display_y + y1, + x2 - x1, y2 - y1); +} + +static void mark(SpiceDisplay *display, gint mark) +{ + SpiceDisplayPrivate *d = display->priv; + g_return_if_fail(d != NULL); + + SPICE_DEBUG("widget mark: %d, %d:%d %p", mark, d->channel_id, d->monitor_id, display); + d->mark = mark; + update_ready(display); +} + +static void cursor_set(SpiceCursorChannel *channel, + gint width, gint height, gint hot_x, gint hot_y, + gpointer rgba, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + GdkCursor *cursor = NULL; + + cursor_invalidate(display); + + g_clear_object(&d->mouse_pixbuf); + + if (rgba != NULL) { + d->mouse_pixbuf = gdk_pixbuf_new_from_data(g_memdup(rgba, width * height * 4), + GDK_COLORSPACE_RGB, + TRUE, 8, + width, + height, + width * 4, + (GdkPixbufDestroyNotify)g_free, NULL); + d->mouse_hotspot.x = hot_x; + d->mouse_hotspot.y = hot_y; + cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display(GTK_WIDGET(display)), + d->mouse_pixbuf, hot_x, hot_y); + } else + g_warn_if_reached(); + +#ifndef G_OS_WIN32 + if (egl_enabled(d)) + spice_egl_cursor_set(display); +#endif + if (d->show_cursor) { + /* unhide */ + g_clear_pointer(&d->show_cursor, g_object_unref); + if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) { + /* keep a hidden cursor, will be shown in cursor_move() */ + d->show_cursor = cursor; + return; + } + } + + g_object_unref(d->mouse_cursor); + d->mouse_cursor = cursor; + + update_mouse_pointer(display); + cursor_invalidate(display); +} + +static void cursor_hide(SpiceCursorChannel *channel, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + + if (d->show_cursor != NULL) /* then we are already hidden */ + return; + + cursor_invalidate(display); + d->show_cursor = d->mouse_cursor; + d->mouse_cursor = get_blank_cursor(); + update_mouse_pointer(display); +} + +G_GNUC_INTERNAL +void spice_display_get_scaling(SpiceDisplay *display, + double *s_out, + int *x_out, int *y_out, + int *w_out, int *h_out) +{ + SpiceDisplayPrivate *d = display->priv; + int fbw = d->area.width, fbh = d->area.height; + int ww, wh; + int x, y, w, h; + double s; + + if (gtk_widget_get_realized (GTK_WIDGET(display))) { + ww = gtk_widget_get_allocated_width(GTK_WIDGET(display)); + wh = gtk_widget_get_allocated_height(GTK_WIDGET(display)); + } else { + ww = fbw; + wh = fbh; + } + + if (!spice_cairo_is_scaled(display)) { + s = 1.0; + x = 0; + y = 0; + if (ww > d->area.width) + x = (ww - d->area.width) / 2; + if (wh > d->area.height) + y = (wh - d->area.height) / 2; + w = fbw; + h = fbh; + } else { + s = MIN ((double)ww / (double)fbw, (double)wh / (double)fbh); + + if (d->only_downscale && s >= 1.0) + s = 1.0; + + /* Round to int size */ + w = floor (fbw * s + 0.5); + h = floor (fbh * s + 0.5); + + /* Center the display */ + x = (ww - w) / 2; + y = (wh - h) / 2; + } + + if (s_out) + *s_out = s; + if (w_out) + *w_out = w; + if (h_out) + *h_out = h; + if (x_out) + *x_out = x; + if (y_out) + *y_out = y; +} + +static void cursor_invalidate(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + double s; + int x, y; + + if (!gtk_widget_get_realized (GTK_WIDGET(display))) + return; + + if (d->mouse_pixbuf == NULL) + return; + + if (!d->ready || !d->monitor_ready) + return; + + spice_display_get_scaling(display, &s, &x, &y, NULL, NULL); + + queue_draw_area(display, + floor ((d->mouse_guest_x - d->mouse_hotspot.x - d->area.x) * s) + x, + floor ((d->mouse_guest_y - d->mouse_hotspot.y - d->area.y) * s) + y, + ceil (gdk_pixbuf_get_width(d->mouse_pixbuf) * s), + ceil (gdk_pixbuf_get_height(d->mouse_pixbuf) * s)); +} + +static void cursor_move(SpiceCursorChannel *channel, gint x, gint y, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + + cursor_invalidate(display); + + d->mouse_guest_x = x; + d->mouse_guest_y = y; + + cursor_invalidate(display); + + /* apparently we have to restore cursor when "cursor_move" */ + if (d->show_cursor != NULL) { + g_object_unref(d->mouse_cursor); + d->mouse_cursor = d->show_cursor; + d->show_cursor = NULL; + update_mouse_pointer(display); + } +} + +static void cursor_reset(SpiceCursorChannel *channel, gpointer data) +{ + SpiceDisplay *display = data; + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(display)); + + if (!window) { + SPICE_DEBUG("%s: no window, returning", __FUNCTION__); + return; + } + + SPICE_DEBUG("%s", __FUNCTION__); + gdk_window_set_cursor(window, NULL); +} + +#ifndef G_OS_WIN32 +G_GNUC_INTERNAL +void spice_display_widget_gl_scanout(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s: got scanout", __FUNCTION__); + set_egl_enabled(display, true); + + if (d->egl.context_ready) { + const SpiceGlScanout *scanout; + GError *err = NULL; + + scanout = spice_display_get_gl_scanout(SPICE_DISPLAY_CHANNEL(d->display)); + /* should only be called when the display has a scanout */ + g_return_if_fail(scanout != NULL); + + if (!spice_egl_update_scanout(display, scanout, &err)) { + g_critical("update scanout failed: %s", err->message); + g_clear_error(&err); + } + } +} + +static void gl_draw(SpiceDisplay *display, + guint32 x, guint32 y, guint32 w, guint32 h) +{ + SpiceDisplayPrivate *d = display->priv; + + SPICE_DEBUG("%s", __FUNCTION__); + + set_egl_enabled(display, true); + + g_return_if_fail(d->egl.context_ready); + +#if GTK_CHECK_VERSION(3,16,0) + GtkWidget *gl = gtk_stack_get_child_by_name(d->stack, "gl-area"); + + if (gtk_stack_get_visible_child(d->stack) == gl) { + gtk_gl_area_queue_render(GTK_GL_AREA(gl)); + d->egl.call_draw_done = TRUE; + } else +#endif + { + spice_egl_update_display(display); + spice_display_gl_draw_done(SPICE_DISPLAY_CHANNEL(d->display)); + } +} +#endif + +static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + int id; + + g_object_get(channel, "channel-id", &id, NULL); + if (SPICE_IS_MAIN_CHANNEL(channel)) { + d->main = SPICE_MAIN_CHANNEL(channel); + spice_g_signal_connect_object(channel, "main-mouse-update", + G_CALLBACK(update_mouse_mode), display, 0); + update_mouse_mode(channel, display); + return; + } + + if (SPICE_IS_DISPLAY_CHANNEL(channel)) { + SpiceDisplayPrimary primary; + if (id != d->channel_id) + return; + d->display = channel; + spice_g_signal_connect_object(channel, "display-primary-create", + G_CALLBACK(primary_create), display, 0); + spice_g_signal_connect_object(channel, "display-primary-destroy", + G_CALLBACK(primary_destroy), display, 0); + spice_g_signal_connect_object(channel, "display-invalidate", + G_CALLBACK(invalidate), display, 0); + spice_g_signal_connect_object(channel, "display-mark", + G_CALLBACK(mark), display, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "notify::monitors", + G_CALLBACK(spice_display_widget_update_monitor_area), + display, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + if (spice_display_get_primary(channel, 0, &primary)) { + primary_create(channel, primary.format, primary.width, primary.height, + primary.stride, primary.shmid, primary.data, display); + mark(display, primary.marked); + } + +#ifndef G_OS_WIN32 + spice_g_signal_connect_object(channel, "notify::gl-scanout", + G_CALLBACK(spice_display_widget_gl_scanout), + display, G_CONNECT_SWAPPED); + spice_g_signal_connect_object(channel, "gl-draw", + G_CALLBACK(gl_draw), display, G_CONNECT_SWAPPED); +#endif + + spice_channel_connect(channel); + return; + } + + if (SPICE_IS_CURSOR_CHANNEL(channel)) { + if (id != d->channel_id) + return; + d->cursor = SPICE_CURSOR_CHANNEL(channel); + spice_g_signal_connect_object(channel, "cursor-set", + G_CALLBACK(cursor_set), display, 0); + spice_g_signal_connect_object(channel, "cursor-move", + G_CALLBACK(cursor_move), display, 0); + spice_g_signal_connect_object(channel, "cursor-hide", + G_CALLBACK(cursor_hide), display, 0); + spice_g_signal_connect_object(channel, "cursor-reset", + G_CALLBACK(cursor_reset), display, 0); + spice_channel_connect(channel); + return; + } + + if (SPICE_IS_INPUTS_CHANNEL(channel)) { + d->inputs = SPICE_INPUTS_CHANNEL(channel); + spice_channel_connect(channel); + return; + } + +#ifdef USE_SMARTCARD + if (SPICE_IS_SMARTCARD_CHANNEL(channel)) { + d->smartcard = SPICE_SMARTCARD_CHANNEL(channel); + spice_channel_connect(channel); + return; + } +#endif + + return; +} + +static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data) +{ + SpiceDisplay *display = data; + SpiceDisplayPrivate *d = display->priv; + int id; + + g_object_get(channel, "channel-id", &id, NULL); + SPICE_DEBUG("channel_destroy %d", id); + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + d->main = NULL; + return; + } + + if (SPICE_IS_DISPLAY_CHANNEL(channel)) { + if (id != d->channel_id) + return; + primary_destroy(d->display, display); + d->display = NULL; + return; + } + + if (SPICE_IS_CURSOR_CHANNEL(channel)) { + if (id != d->channel_id) + return; + d->cursor = NULL; + return; + } + + if (SPICE_IS_INPUTS_CHANNEL(channel)) { + d->inputs = NULL; + return; + } + +#ifdef USE_SMARTCARD + if (SPICE_IS_SMARTCARD_CHANNEL(channel)) { + d->smartcard = NULL; + return; + } +#endif + + return; +} + +/** + * spice_display_new: + * @session: a #SpiceSession + * @channel_id: the display channel ID to associate with #SpiceDisplay + * + * Creates a new #SpiceDisplay widget. + * + * Returns: a new #SpiceDisplay widget. + **/ +SpiceDisplay *spice_display_new(SpiceSession *session, int channel_id) +{ + return g_object_new(SPICE_TYPE_DISPLAY, "session", session, + "channel-id", channel_id, NULL); +} + +/** + * spice_display_new_with_monitor: + * @session: a #SpiceSession + * @channel_id: the display channel ID to associate with #SpiceDisplay + * @monitor_id: the monitor id within the display channel + * + * Creates a new #SpiceDisplay widget associated with the monitor id. + * + * Since: 0.13 + * Returns: a new #SpiceDisplay widget. + **/ +SpiceDisplay* spice_display_new_with_monitor(SpiceSession *session, gint channel_id, gint monitor_id) +{ + return g_object_new(SPICE_TYPE_DISPLAY, + "session", session, + "channel-id", channel_id, + "monitor-id", monitor_id, + NULL); +} + +/** + * spice_display_mouse_ungrab: + * @display: a #SpiceDisplay + * + * Ungrab the mouse. + **/ +void spice_display_mouse_ungrab(SpiceDisplay *display) +{ + g_return_if_fail(SPICE_IS_DISPLAY(display)); + + try_mouse_ungrab(display); +} + +/** + * spice_display_get_pixbuf: + * @display: a #SpiceDisplay + * + * Take a screenshot of the display. + * + * Returns: (transfer full): a #GdkPixbuf with the screenshot image buffer + **/ +GdkPixbuf *spice_display_get_pixbuf(SpiceDisplay *display) +{ + SpiceDisplayPrivate *d; + GdkPixbuf *pixbuf; + guchar *data; + + g_return_val_if_fail(SPICE_IS_DISPLAY(display), NULL); + + d = display->priv; + + g_return_val_if_fail(d != NULL, NULL); + g_return_val_if_fail(d->display != NULL, NULL); + +#ifndef G_OS_WIN32 + if (egl_enabled(d)) { + GdkPixbuf *tmp; + + data = g_malloc0(d->area.width * d->area.height * 4); + glReadBuffer(GL_FRONT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glReadPixels(0, 0, d->area.width, d->area.height, + GL_RGBA, GL_UNSIGNED_BYTE, data); + tmp = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, true, + 8, d->area.width, d->area.height, + d->area.width * 4, + (GdkPixbufDestroyNotify)g_free, NULL); + pixbuf = gdk_pixbuf_flip(tmp, false); + g_object_unref(tmp); + } else +#endif + { + guchar *src, *dest; + int x, y; + + /* TODO: ensure d->data has been exposed? */ + g_return_val_if_fail(d->canvas.data != NULL, NULL); + data = g_malloc0(d->area.width * d->area.height * 3); + src = d->canvas.data; + dest = data; + + src += d->area.y * d->canvas.stride + d->area.x * 4; + for (y = 0; y < d->area.height; ++y) { + for (x = 0; x < d->area.width; ++x) { + dest[0] = src[x * 4 + 2]; + dest[1] = src[x * 4 + 1]; + dest[2] = src[x * 4 + 0]; + dest += 3; + } + src += d->canvas.stride; + } + pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, false, + 8, d->area.width, d->area.height, + d->area.width * 3, + (GdkPixbufDestroyNotify)g_free, NULL); + } + + return pixbuf; +} diff --git a/src/spice-widget.h b/src/spice-widget.h new file mode 100644 index 0000000..a8adf9c --- /dev/null +++ b/src/spice-widget.h @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#ifndef __SPICE_CLIENT_WIDGET_H__ +#define __SPICE_CLIENT_WIDGET_H__ + +#if !defined(__SPICE_CLIENT_GTK_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only can be included directly" +#endif + +#include "spice-client.h" + +#include +#include "spice-grabsequence.h" +#include "spice-widget-enums.h" +#include "spice-util.h" +#include "spice-gtk-session.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_DISPLAY (spice_display_get_type()) +#define SPICE_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_DISPLAY, SpiceDisplay)) +#define SPICE_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_DISPLAY, SpiceDisplayClass)) +#define SPICE_IS_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_DISPLAY)) +#define SPICE_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_DISPLAY)) +#define SPICE_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_DISPLAY, SpiceDisplayClass)) + + +typedef struct _SpiceDisplay SpiceDisplay; +typedef struct _SpiceDisplayClass SpiceDisplayClass; + +/** + * SpiceDisplayKeyEvent: + * @SPICE_DISPLAY_KEY_EVENT_PRESS: key press + * @SPICE_DISPLAY_KEY_EVENT_RELEASE: key release + * @SPICE_DISPLAY_KEY_EVENT_CLICK: key click (press and release) + * + * Constants for key events. + */ +typedef enum +{ + SPICE_DISPLAY_KEY_EVENT_PRESS = 1, + SPICE_DISPLAY_KEY_EVENT_RELEASE = 2, + SPICE_DISPLAY_KEY_EVENT_CLICK = 3, +} SpiceDisplayKeyEvent; + +GType spice_display_get_type(void); + +SpiceDisplay* spice_display_new(SpiceSession *session, int channel_id); +SpiceDisplay* spice_display_new_with_monitor(SpiceSession *session, gint channel_id, gint monitor_id); + +void spice_display_mouse_ungrab(SpiceDisplay *display); +void spice_display_set_grab_keys(SpiceDisplay *display, SpiceGrabSequence *seq); +SpiceGrabSequence *spice_display_get_grab_keys(SpiceDisplay *display); +void spice_display_send_keys(SpiceDisplay *display, const guint *keyvals, + int nkeyvals, SpiceDisplayKeyEvent kind); +GdkPixbuf *spice_display_get_pixbuf(SpiceDisplay *display); + +G_END_DECLS + +#endif /* __SPICE_CLIENT_WIDGET_H__ */ diff --git a/src/spicy-connect.c b/src/spicy-connect.c new file mode 100644 index 0000000..c471df5 --- /dev/null +++ b/src/spicy-connect.c @@ -0,0 +1,248 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include +#include +#include "spice-common.h" +#include "spicy-connect.h" + +typedef struct +{ + gboolean connecting; + GMainLoop *loop; + SpiceSession *session; +} ConnectionInfo; + +static struct { + const char *text; + const char *prop; + GtkWidget *entry; +} connect_entries[] = { + { .text = "Hostname", .prop = "host" }, + { .text = "Port", .prop = "port" }, + { .text = "TLS Port", .prop = "tls-port" }, +}; + +static gboolean can_connect(void) +{ + if ((gtk_entry_get_text_length(GTK_ENTRY(connect_entries[0].entry)) > 0) && + ((gtk_entry_get_text_length(GTK_ENTRY(connect_entries[1].entry)) > 0) || + (gtk_entry_get_text_length(GTK_ENTRY(connect_entries[2].entry)) > 0))) + return TRUE; + + return FALSE; +} + +static void set_connection_info(SpiceSession *session) +{ + const gchar *txt; + int i; + + for (i = 0; i < SPICE_N_ELEMENTS(connect_entries); i++) { + txt = gtk_entry_get_text(GTK_ENTRY(connect_entries[i].entry)); + g_object_set(session, connect_entries[i].prop, txt, NULL); + } +} + +static gboolean close_cb(gpointer data) +{ + ConnectionInfo *info = data; + info->connecting = FALSE; + if (g_main_loop_is_running(info->loop)) + g_main_loop_quit(info->loop); + + return TRUE; +} + +static void entry_changed_cb(GtkEditable* entry, gpointer data) +{ + GtkButton *connect_button = data; + gtk_widget_set_sensitive(GTK_WIDGET(connect_button), can_connect()); +} + +static gboolean entry_focus_in_cb(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + GtkRecentChooser *recent = GTK_RECENT_CHOOSER(data); + gtk_recent_chooser_unselect_all(recent); + return TRUE; +} + +static gboolean key_pressed_cb(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + gboolean tst; + if (event->type == GDK_KEY_PRESS) { + switch (event->key.keyval) { + case GDK_KEY_Escape: + g_signal_emit_by_name(GTK_WIDGET(data), "delete-event", NULL, &tst); + return TRUE; + default: + return FALSE; + } + } + + return FALSE; +} + +static void recent_selection_changed_dialog_cb(GtkRecentChooser *chooser, gpointer data) +{ + GtkRecentInfo *info; + gchar *txt = NULL; + const gchar *uri; + SpiceSession *session = data; + int i; + + info = gtk_recent_chooser_get_current_item(chooser); + if (info == NULL) + return; + + uri = gtk_recent_info_get_uri(info); + g_return_if_fail(uri != NULL); + + g_object_set(session, "uri", uri, NULL); + + for (i = 0; i < SPICE_N_ELEMENTS(connect_entries); i++) { + g_object_get(session, connect_entries[i].prop, &txt, NULL); + gtk_entry_set_text(GTK_ENTRY(connect_entries[i].entry), txt ? txt : ""); + g_free(txt); + } + + gtk_recent_info_unref(info); +} + +static void connect_cb(gpointer data) +{ + ConnectionInfo *info = data; + if (can_connect()) + { + info->connecting = TRUE; + set_connection_info(info->session); + if (g_main_loop_is_running(info->loop)) + g_main_loop_quit(info->loop); + } +} + +gboolean spicy_connect_dialog(SpiceSession *session) +{ + GtkWidget *connect_button, *cancel_button, *label; + GtkBox *main_box, *recent_box, *button_box; + GtkWindow *window; + GtkTable *table; + int i; + + ConnectionInfo info = { + FALSE, + NULL, + session + }; + + /* Create the widgets */ + window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); + gtk_window_set_title(window, "Connect to SPICE"); + gtk_window_set_resizable(window, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(window), 5); + + main_box = GTK_BOX(gtk_vbox_new(FALSE, 0)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(main_box)); + + table = GTK_TABLE(gtk_table_new(3, 2, 0)); + gtk_box_pack_start(main_box, GTK_WIDGET(table), FALSE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + gtk_table_set_row_spacings(table, 5); + gtk_table_set_col_spacings(table, 5); + + for (i = 0; i < SPICE_N_ELEMENTS(connect_entries); i++) { + gchar *txt; + label = gtk_label_new(connect_entries[i].text); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_table_attach_defaults(table, label, 0, 1, i, i+1); + connect_entries[i].entry = GTK_WIDGET(gtk_entry_new()); + gtk_table_attach_defaults(table, connect_entries[i].entry, 1, 2, i, i+1); + g_object_get(session, connect_entries[i].prop, &txt, NULL); + SPICE_DEBUG("%s: #%i [%s]: \"%s\"", + __FUNCTION__, i, connect_entries[i].prop, txt); + if (txt) { + gtk_entry_set_text(GTK_ENTRY(connect_entries[i].entry), txt); + g_free(txt); + } + } + + recent_box = GTK_BOX(gtk_vbox_new(FALSE, 0)); + gtk_box_pack_start(main_box, GTK_WIDGET(recent_box), TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(recent_box), 5); + + label = gtk_label_new("Recent connections:"); + gtk_box_pack_start(recent_box, label, FALSE, TRUE, 0); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + button_box = GTK_BOX(gtk_hbutton_box_new()); + gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END); + gtk_box_set_spacing(button_box, 5); + gtk_container_set_border_width(GTK_CONTAINER(button_box), 5); + connect_button = gtk_button_new_with_label("Connect"); + cancel_button = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(button_box, cancel_button, FALSE, TRUE, 0); + gtk_box_pack_start(button_box, connect_button, FALSE, TRUE, 1); + + gtk_box_pack_start(main_box, GTK_WIDGET(button_box), FALSE, TRUE, 0); + + gtk_widget_set_sensitive(GTK_WIDGET(connect_button), can_connect()); + + g_signal_connect(window, "key-press-event", + G_CALLBACK(key_pressed_cb), window); + g_signal_connect_swapped(window, "delete-event", + G_CALLBACK(close_cb), &info); + g_signal_connect_swapped(connect_button, "clicked", + G_CALLBACK(connect_cb), &info); + g_signal_connect_swapped(cancel_button, "clicked", + G_CALLBACK(close_cb), &info); + + GtkRecentFilter *rfilter; + GtkWidget *recent; + + recent = GTK_WIDGET(gtk_recent_chooser_widget_new()); + gtk_recent_chooser_set_show_icons(GTK_RECENT_CHOOSER(recent), FALSE); + gtk_box_pack_start(recent_box, recent, TRUE, TRUE, 0); + + rfilter = gtk_recent_filter_new(); + gtk_recent_filter_add_mime_type(rfilter, "application/x-spice"); + gtk_recent_chooser_set_filter(GTK_RECENT_CHOOSER(recent), rfilter); + gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(recent), FALSE); + g_signal_connect(recent, "selection-changed", + G_CALLBACK(recent_selection_changed_dialog_cb), session); + g_signal_connect_swapped(recent, "item-activated", + G_CALLBACK(connect_cb), &info); + + for (i = 0; i < SPICE_N_ELEMENTS(connect_entries); i++) { + g_signal_connect_swapped(connect_entries[i].entry, "activate", + G_CALLBACK(connect_cb), &info); + g_signal_connect(connect_entries[i].entry, "changed", + G_CALLBACK(entry_changed_cb), connect_button); + g_signal_connect(connect_entries[i].entry, "focus-in-event", + G_CALLBACK(entry_focus_in_cb), recent); + } + + /* show and wait for response */ + gtk_widget_show_all(GTK_WIDGET(window)); + + info.loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(info.loop); + + gtk_widget_destroy(GTK_WIDGET(window)); + + return info.connecting; +} diff --git a/src/spicy-connect.h b/src/spicy-connect.h new file mode 100644 index 0000000..56b2d80 --- /dev/null +++ b/src/spicy-connect.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef SPICY_CONNECT_H +#define SPICY_CONNECT_H + +#include "spice-widget.h" + +gboolean spicy_connect_dialog(SpiceSession *session); + +#endif diff --git a/src/spicy-screenshot.c b/src/spicy-screenshot.c new file mode 100644 index 0000000..68f9335 --- /dev/null +++ b/src/spicy-screenshot.c @@ -0,0 +1,194 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-cmdline.h" + +/* config */ +static const char *outf = "spicy-screenshot.ppm"; +static gboolean version = FALSE; + +/* state */ +static SpiceSession *session; +static GMainLoop *mainloop; + +enum SpiceSurfaceFmt d_format; +gint d_width, d_height, d_stride; +gpointer d_data; + +/* ------------------------------------------------------------------ */ + +static void primary_create(SpiceChannel *channel, gint format, + gint width, gint height, gint stride, + gint shmid, gpointer imgdata, gpointer data) +{ + SPICE_DEBUG("%s: %dx%d, format %d", __FUNCTION__, width, height, format); + d_format = format; + d_width = width; + d_height = height; + d_stride = stride; + d_data = imgdata; +} + +static int write_ppm_32(void) +{ + FILE *fp; + uint8_t *p; + int n; + + fp = fopen(outf,"w"); + if (NULL == fp) { + fprintf(stderr, "%s: can't open %s: %s\n", g_get_prgname(), outf, strerror(errno)); + return -1; + } + fprintf(fp, "P6\n%d %d\n255\n", + d_width, d_height); + n = d_width * d_height; + p = d_data; + while (n > 0) { +#ifdef WORDS_BIGENDIAN + fputc(p[1], fp); + fputc(p[2], fp); + fputc(p[3], fp); +#else + fputc(p[2], fp); + fputc(p[1], fp); + fputc(p[0], fp); +#endif + p += 4; + n--; + } + fclose(fp); + return 0; +} + +static void invalidate(SpiceChannel *channel, + gint x, gint y, gint w, gint h, gpointer *data) +{ + int rc; + + switch (d_format) { + case SPICE_SURFACE_FMT_32_xRGB: + rc = write_ppm_32(); + break; + default: + fprintf(stderr, "unsupported spice surface format %u\n", d_format); + rc = -1; + break; + } + if (rc == 0) + fprintf(stderr, "wrote screen shot to %s\n", outf); + g_main_loop_quit(mainloop); +} + +static void main_channel_event(SpiceChannel *channel, SpiceChannelEvent event, + gpointer data) +{ + switch (event) { + case SPICE_CHANNEL_OPENED: + break; + default: + g_warning("main channel event: %u", event); + g_main_loop_quit(mainloop); + } +} + +static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer *data) +{ + int id; + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + g_signal_connect(channel, "channel-event", + G_CALLBACK(main_channel_event), data); + return; + } + + if (!SPICE_IS_DISPLAY_CHANNEL(channel)) + return; + + g_object_get(channel, "channel-id", &id, NULL); + if (id != 0) + return; + + g_signal_connect(channel, "display-primary-create", + G_CALLBACK(primary_create), NULL); + g_signal_connect(channel, "display-invalidate", + G_CALLBACK(invalidate), NULL); + spice_channel_connect(channel); +} + +/* ------------------------------------------------------------------ */ + +static GOptionEntry app_entries[] = { + { + .long_name = "out-file", + .short_name = 'o', + .arg = G_OPTION_ARG_FILENAME, + .arg_data = &outf, + .description = "Output file name (default spicy-screenshot.ppm)", + .arg_description = "", + }, + { + .long_name = "version", + .arg = G_OPTION_ARG_NONE, + .arg_data = &version, + .description = "Display version and quit", + }, + { + /* end of list */ + } +}; + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + + /* parse opts */ + context = g_option_context_new(" - make screen shots"); + g_option_context_set_summary(context, "A Spice server client to take screenshots in ppm format."); + g_option_context_set_description(context, "Report bugs to " PACKAGE_BUGREPORT "."); + g_option_context_set_main_group(context, spice_cmdline_get_option_group()); + g_option_context_add_main_entries(context, app_entries, NULL); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print("option parsing failed: %s\n", error->message); + exit(1); + } + + if (version) { + g_print("%s " PACKAGE_VERSION "\n", g_get_prgname()); + exit(0); + } + + mainloop = g_main_loop_new(NULL, false); + + session = spice_session_new(); + g_signal_connect(session, "channel-new", + G_CALLBACK(channel_new), NULL); + spice_cmdline_session_setup(session); + + if (!spice_session_connect(session)) { + fprintf(stderr, "spice_session_connect failed\n"); + exit(1); + } + + g_main_loop_run(mainloop); + return 0; +} diff --git a/src/spicy-stats.c b/src/spicy-stats.c new file mode 100644 index 0000000..8ca4cc1 --- /dev/null +++ b/src/spicy-stats.c @@ -0,0 +1,136 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "config.h" + +#include "spice-client.h" +#include "spice-common.h" +#include "spice-cmdline.h" + +/* config */ +static gboolean version = FALSE; + +/* state */ +static SpiceSession *session; +static GMainLoop *mainloop; + +/* ------------------------------------------------------------------ */ +static void main_channel_event(SpiceChannel *channel, SpiceChannelEvent event, + gpointer data) +{ + switch (event) { + case SPICE_CHANNEL_OPENED: + break; + default: + g_warning("main channel event: %u", event); + g_main_loop_quit(mainloop); + } +} + +static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer *data) +{ + int id; + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + SPICE_DEBUG("new main channel"); + g_signal_connect(channel, "channel-event", + G_CALLBACK(main_channel_event), data); + } + + if (SPICE_IS_DISPLAY_CHANNEL(channel)) { + g_object_get(channel, "channel-id", &id, NULL); + if (id != 0) + return; + } + + spice_channel_connect(channel); +} + +/* ------------------------------------------------------------------ */ + +static GOptionEntry app_entries[] = { + { + .long_name = "version", + .arg = G_OPTION_ARG_NONE, + .arg_data = &version, + .description = "Display version and quit", + }, + { + /* end of list */ + } +}; + +static void +signal_handler(int signum) +{ + g_main_loop_quit(mainloop); +} + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + + signal(SIGINT, signal_handler); + + /* parse opts */ + context = g_option_context_new(NULL); + g_option_context_set_summary(context, "A Spice client used for testing and measurements."); + g_option_context_set_description(context, "Report bugs to " PACKAGE_BUGREPORT "."); + g_option_context_set_main_group(context, spice_cmdline_get_option_group()); + g_option_context_add_main_entries(context, app_entries, NULL); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print("option parsing failed: %s\n", error->message); + exit(1); + } + + if (version) { + g_print("spicy-stats " PACKAGE_VERSION "\n"); + exit(0); + } + + mainloop = g_main_loop_new(NULL, false); + + session = spice_session_new(); + g_signal_connect(session, "channel-new", + G_CALLBACK(channel_new), NULL); + spice_cmdline_session_setup(session); + + if (!spice_session_connect(session)) { + fprintf(stderr, "spice_session_connect failed\n"); + exit(1); + } + + g_main_loop_run(mainloop); + { + GList *iter, *list = spice_session_get_channels(session); + gulong total_read_bytes; + gint channel_type; + printf("total bytes read:\n"); + for (iter = list ; iter ; iter = iter->next) { + g_object_get(iter->data, + "total-read-bytes", &total_read_bytes, + "channel-type", &channel_type, + NULL); + printf("%s: %lu\n", + spice_channel_type_to_string(channel_type), + total_read_bytes); + } + g_list_free(list); + } + return 0; +} diff --git a/src/spicy.c b/src/spicy.c new file mode 100644 index 0000000..ea4d4e0 --- /dev/null +++ b/src/spicy.c @@ -0,0 +1,1930 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2010-2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "config.h" +#include + +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#ifdef USE_SMARTCARD_012 +#include +#endif + +#include "spice-widget.h" +#include "spice-gtk-session.h" +#include "spice-audio.h" +#include "spice-common.h" +#include "spice-cmdline.h" +#include "spice-option.h" +#include "usb-device-widget.h" + +#include "spicy-connect.h" + +typedef struct spice_connection spice_connection; + +enum { + STATE_SCROLL_LOCK, + STATE_CAPS_LOCK, + STATE_NUM_LOCK, + STATE_MAX, +}; + +#define SPICE_TYPE_WINDOW (spice_window_get_type ()) +#define SPICE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_WINDOW, SpiceWindow)) +#define SPICE_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_WINDOW)) +#define SPICE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_WINDOW, SpiceWindowClass)) +#define SPICE_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_WINDOW)) +#define SPICE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_WINDOW, SpiceWindowClass)) + +typedef struct _SpiceWindow SpiceWindow; +typedef struct _SpiceWindowClass SpiceWindowClass; + +struct _SpiceWindow { + GObject object; + spice_connection *conn; + gint id; + gint monitor_id; + GtkWidget *toplevel, *spice; + GtkWidget *menubar, *toolbar; + GtkWidget *ritem, *rmenu; + GtkWidget *statusbar, *status, *st[STATE_MAX]; + GtkActionGroup *ag; + GtkUIManager *ui; + bool fullscreen; + bool mouse_grabbed; + SpiceChannel *display_channel; +#ifdef G_OS_WIN32 + gint win_x; + gint win_y; +#endif + bool enable_accels_save; + bool enable_mnemonics_save; +}; + +struct _SpiceWindowClass +{ + GObjectClass parent_class; +}; + +static GType spice_window_get_type(void); + +G_DEFINE_TYPE (SpiceWindow, spice_window, G_TYPE_OBJECT); + +#define CHANNELID_MAX 4 +#define MONITORID_MAX 4 + + +// FIXME: turn this into an object, get rid of fixed wins array, use +// signals to replace the various callback that iterate over wins array +struct spice_connection { + SpiceSession *session; + SpiceGtkSession *gtk_session; + SpiceMainChannel *main; + SpiceWindow *wins[CHANNELID_MAX * MONITORID_MAX]; + SpiceAudio *audio; + const char *mouse_state; + const char *agent_state; + gboolean agent_connected; + int channels; + int disconnecting; + + /* key: SpiceFileTransferTask, value: TransferTaskWidgets */ + GHashTable *transfers; + GtkWidget *transfer_dialog; +}; + +static spice_connection *connection_new(void); +static void connection_connect(spice_connection *conn); +static void connection_disconnect(spice_connection *conn); +static void connection_destroy(spice_connection *conn); +static void usb_connect_failed(GObject *object, + SpiceUsbDevice *device, + GError *error, + gpointer data); +static gboolean is_gtk_session_property(const gchar *property); +static void del_window(spice_connection *conn, SpiceWindow *win); + +/* options */ +static gboolean fullscreen = false; +static gboolean version = false; +static char *spicy_title = NULL; +/* globals */ +static GMainLoop *mainloop = NULL; +static int connections = 0; +static GKeyFile *keyfile = NULL; +static SpicePortChannel*stdin_port = NULL; + +/* ------------------------------------------------------------------ */ + +static int ask_user(GtkWidget *parent, char *title, char *message, + char *dest, int dlen, int hide) +{ + GtkWidget *dialog, *area, *label, *entry; + const char *txt; + int retval; + + /* Create the widgets */ + dialog = gtk_dialog_new_with_buttons(title, + parent ? GTK_WINDOW(parent) : NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + "_OK", + GTK_RESPONSE_ACCEPT, + "_Cancel", + GTK_RESPONSE_REJECT, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + label = gtk_label_new(message); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(area), label, FALSE, FALSE, 5); + + entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(entry), dest); + gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); + if (hide) + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_box_pack_start(GTK_BOX(area), entry, FALSE, FALSE, 5); + + /* show and wait for response */ + gtk_widget_show_all(dialog); + switch (gtk_dialog_run(GTK_DIALOG(dialog))) { + case GTK_RESPONSE_ACCEPT: + txt = gtk_entry_get_text(GTK_ENTRY(entry)); + snprintf(dest, dlen, "%s", txt); + retval = 0; + break; + default: + retval = -1; + break; + } + gtk_widget_destroy(dialog); + return retval; +} + +static void update_status_window(SpiceWindow *win) +{ + gchar *status; + + if (win == NULL) + return; + + if (win->mouse_grabbed) { + SpiceGrabSequence *sequence = spice_display_get_grab_keys(SPICE_DISPLAY(win->spice)); + gchar *seq = spice_grab_sequence_as_string(sequence); + status = g_strdup_printf("Use %s to ungrab mouse.", seq); + g_free(seq); + } else { + status = g_strdup_printf("mouse: %s, agent: %s", + win->conn->mouse_state, win->conn->agent_state); + } + + gtk_label_set_text(GTK_LABEL(win->status), status); + g_free(status); +} + +static void update_status(struct spice_connection *conn) +{ + int i; + + for (i = 0; i < SPICE_N_ELEMENTS(conn->wins); i++) { + if (conn->wins[i] == NULL) + continue; + update_status_window(conn->wins[i]); + } +} + +static const char *spice_edit_properties[] = { + "CopyToGuest", + "PasteFromGuest", +}; + +static void update_edit_menu_window(SpiceWindow *win) +{ + int i; + GtkAction *toggle; + + if (win == NULL) { + return; + } + + /* Make "CopyToGuest" and "PasteFromGuest" insensitive if spice + * agent is not connected */ + for (i = 0; i < G_N_ELEMENTS(spice_edit_properties); i++) { + toggle = gtk_action_group_get_action(win->ag, spice_edit_properties[i]); + if (toggle) { + gtk_action_set_sensitive(toggle, win->conn->agent_connected); + } + } +} + +static void update_edit_menu(struct spice_connection *conn) +{ + int i; + + for (i = 0; i < SPICE_N_ELEMENTS(conn->wins); i++) { + if (conn->wins[i]) { + update_edit_menu_window(conn->wins[i]); + } + } +} + +static void menu_cb_connect(GtkAction *action, void *data) +{ + struct spice_connection *conn; + + conn = connection_new(); + connection_connect(conn); +} + +static void menu_cb_close(GtkAction *action, void *data) +{ + SpiceWindow *win = data; + + connection_disconnect(win->conn); +} + +static void menu_cb_copy(GtkAction *action, void *data) +{ + SpiceWindow *win = data; + + spice_gtk_session_copy_to_guest(win->conn->gtk_session); +} + +static void menu_cb_paste(GtkAction *action, void *data) +{ + SpiceWindow *win = data; + + spice_gtk_session_paste_from_guest(win->conn->gtk_session); +} + +static void window_set_fullscreen(SpiceWindow *win, gboolean fs) +{ + if (fs) { +#ifdef G_OS_WIN32 + gtk_window_get_position(GTK_WINDOW(win->toplevel), &win->win_x, &win->win_y); +#endif + gtk_window_fullscreen(GTK_WINDOW(win->toplevel)); + } else { + gtk_window_unfullscreen(GTK_WINDOW(win->toplevel)); +#ifdef G_OS_WIN32 + gtk_window_move(GTK_WINDOW(win->toplevel), win->win_x, win->win_y); +#endif + } +} + +static void menu_cb_fullscreen(GtkAction *action, void *data) +{ + SpiceWindow *win = data; + + window_set_fullscreen(win, !win->fullscreen); +} + +#ifdef USE_SMARTCARD +static void enable_smartcard_actions(SpiceWindow *win, VReader *reader, + gboolean can_insert, gboolean can_remove) +{ + GtkAction *action; + + if ((reader != NULL) && (!spice_smartcard_reader_is_software((SpiceSmartcardReader*)reader))) + { + /* Having menu actions to insert/remove smartcards only makes sense + * for software smartcard readers, don't do anything when the event + * we received was for a "real" smartcard reader. + */ + return; + } + action = gtk_action_group_get_action(win->ag, "InsertSmartcard"); + g_return_if_fail(action != NULL); + gtk_action_set_sensitive(action, can_insert); + action = gtk_action_group_get_action(win->ag, "RemoveSmartcard"); + g_return_if_fail(action != NULL); + gtk_action_set_sensitive(action, can_remove); +} + + +static void reader_added_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + enable_smartcard_actions(user_data, reader, TRUE, FALSE); +} + +static void reader_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + enable_smartcard_actions(user_data, reader, FALSE, FALSE); +} + +static void card_inserted_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + enable_smartcard_actions(user_data, reader, FALSE, TRUE); +} + +static void card_removed_cb(SpiceSmartcardManager *manager, VReader *reader, + gpointer user_data) +{ + enable_smartcard_actions(user_data, reader, TRUE, FALSE); +} + +static void menu_cb_insert_smartcard(GtkAction *action, void *data) +{ + spice_smartcard_manager_insert_card(spice_smartcard_manager_get()); +} + +static void menu_cb_remove_smartcard(GtkAction *action, void *data) +{ + spice_smartcard_manager_remove_card(spice_smartcard_manager_get()); +} +#endif + +static void menu_cb_mouse_mode(GtkAction *action, void *data) +{ + SpiceWindow *win = data; + SpiceMainChannel *cmain = win->conn->main; + int mode; + + g_object_get(cmain, "mouse-mode", &mode, NULL); + if (mode == SPICE_MOUSE_MODE_CLIENT) + mode = SPICE_MOUSE_MODE_SERVER; + else + mode = SPICE_MOUSE_MODE_CLIENT; + + spice_main_request_mouse_mode(cmain, mode); +} + +#ifdef USE_USBREDIR +static void remove_cb(GtkContainer *container, GtkWidget *widget, void *data) +{ + gtk_window_resize(GTK_WINDOW(data), 1, 1); +} + +static void menu_cb_select_usb_devices(GtkAction *action, void *data) +{ + GtkWidget *dialog, *area, *usb_device_widget; + SpiceWindow *win = data; + + /* Create the widgets */ + dialog = gtk_dialog_new_with_buttons( + "Select USB devices for redirection", + GTK_WINDOW(win->toplevel), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + "_Close", GTK_RESPONSE_ACCEPT, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + gtk_container_set_border_width(GTK_CONTAINER(dialog), 12); + gtk_box_set_spacing(GTK_BOX(gtk_bin_get_child(GTK_BIN(dialog))), 12); + + area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + usb_device_widget = spice_usb_device_widget_new(win->conn->session, + NULL); /* default format */ + g_signal_connect(usb_device_widget, "connect-failed", + G_CALLBACK(usb_connect_failed), NULL); + gtk_box_pack_start(GTK_BOX(area), usb_device_widget, TRUE, TRUE, 0); + + /* This shrinks the dialog when USB devices are unplugged */ + g_signal_connect(usb_device_widget, "remove", + G_CALLBACK(remove_cb), dialog); + + /* show and run */ + gtk_widget_show_all(dialog); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} +#endif + +static void menu_cb_bool_prop(GtkToggleAction *action, gpointer data) +{ + SpiceWindow *win = data; + gboolean state = gtk_toggle_action_get_active(action); + const char *name; + gpointer object; + + name = gtk_action_get_name(GTK_ACTION(action)); + SPICE_DEBUG("%s: %s = %s", __FUNCTION__, name, state ? "yes" : "no"); + + g_key_file_set_boolean(keyfile, "general", name, state); + + if (is_gtk_session_property(name)) { + object = win->conn->gtk_session; + } else { + object = win->spice; + } + g_object_set(object, name, state, NULL); +} + +static void menu_cb_conn_bool_prop_changed(GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + SpiceWindow *win = user_data; + const gchar *property = g_param_spec_get_name(pspec); + GtkAction *toggle; + gboolean state; + + toggle = gtk_action_group_get_action(win->ag, property); + g_object_get(win->conn->gtk_session, property, &state, NULL); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggle), state); +} + +static void menu_cb_toolbar(GtkToggleAction *action, gpointer data) +{ + SpiceWindow *win = data; + gboolean state = gtk_toggle_action_get_active(action); + + gtk_widget_set_visible(win->toolbar, state); + g_key_file_set_boolean(keyfile, "ui", "toolbar", state); +} + +static void menu_cb_statusbar(GtkToggleAction *action, gpointer data) +{ + SpiceWindow *win = data; + gboolean state = gtk_toggle_action_get_active(action); + + gtk_widget_set_visible(win->statusbar, state); + g_key_file_set_boolean(keyfile, "ui", "statusbar", state); +} + +static void menu_cb_about(GtkAction *action, void *data) +{ + char *comments = "gtk test client app for the\n" + "spice remote desktop protocol"; + static const char *copyright = "(c) 2010 Red Hat"; + static const char *website = "http://www.spice-space.org"; + static const char *authors[] = { "Gerd Hoffmann ", + "Marc-André Lureau ", + NULL }; + SpiceWindow *win = data; + + gtk_show_about_dialog(GTK_WINDOW(win->toplevel), + "authors", authors, + "comments", comments, + "copyright", copyright, + "logo-icon-name", "help-about", + "website", website, + "version", PACKAGE_VERSION, + "license", "LGPLv2.1", + NULL); +} + +static gboolean delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + SpiceWindow *win = data; + + if (win->monitor_id == 0) + connection_disconnect(win->conn); + else + del_window(win->conn, win); + + return true; +} + +static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event, + gpointer data) +{ + SpiceWindow *win = data; + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { + win->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + if (win->fullscreen) { + gtk_widget_hide(win->menubar); + gtk_widget_hide(win->toolbar); + gtk_widget_hide(win->statusbar); + gtk_widget_grab_focus(win->spice); + } else { + gboolean state; + GtkAction *toggle; + + gtk_widget_show(win->menubar); + toggle = gtk_action_group_get_action(win->ag, "Toolbar"); + state = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(toggle)); + gtk_widget_set_visible(win->toolbar, state); + toggle = gtk_action_group_get_action(win->ag, "Statusbar"); + state = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(toggle)); + gtk_widget_set_visible(win->statusbar, state); + } + } + return TRUE; +} + +static void grab_keys_pressed_cb(GtkWidget *widget, gpointer data) +{ + SpiceWindow *win = data; + + /* since mnemonics are disabled, we leave fullscreen when + ungrabbing mouse. Perhaps we should have a different handling + of fullscreen key, or simply use a UI, like vinagre */ + window_set_fullscreen(win, FALSE); +} + +static void mouse_grab_cb(GtkWidget *widget, gint grabbed, gpointer data) +{ + SpiceWindow *win = data; + + win->mouse_grabbed = grabbed; + update_status(win->conn); +} + +static void keyboard_grab_cb(GtkWidget *widget, gint grabbed, gpointer data) +{ + SpiceWindow *win = data; + GtkSettings *settings = gtk_widget_get_settings (widget); + + if (grabbed) { + /* disable mnemonics & accels */ + g_object_get(settings, + "gtk-enable-accels", &win->enable_accels_save, + "gtk-enable-mnemonics", &win->enable_mnemonics_save, + NULL); + g_object_set(settings, + "gtk-enable-accels", FALSE, + "gtk-enable-mnemonics", FALSE, + NULL); + } else { + g_object_set(settings, + "gtk-enable-accels", win->enable_accels_save, + "gtk-enable-mnemonics", win->enable_mnemonics_save, + NULL); + } +} + +static void restore_configuration(SpiceWindow *win) +{ + gboolean state; + gchar *str; + gchar **keys = NULL; + gsize nkeys, i; + GError *error = NULL; + gpointer object; + + keys = g_key_file_get_keys(keyfile, "general", &nkeys, &error); + if (error != NULL) { + if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) + g_warning("Failed to read configuration file keys: %s", error->message); + g_clear_error(&error); + return; + } + + if (nkeys > 0) + g_return_if_fail(keys != NULL); + + for (i = 0; i < nkeys; ++i) { + if (g_str_equal(keys[i], "grab-sequence")) + continue; + state = g_key_file_get_boolean(keyfile, "general", keys[i], &error); + if (error != NULL) { + g_clear_error(&error); + continue; + } + + if (is_gtk_session_property(keys[i])) { + object = win->conn->gtk_session; + } else { + object = win->spice; + } + g_object_set(object, keys[i], state, NULL); + } + + g_strfreev(keys); + + str = g_key_file_get_string(keyfile, "general", "grab-sequence", &error); + if (error == NULL) { + SpiceGrabSequence *seq = spice_grab_sequence_new_from_string(str); + spice_display_set_grab_keys(SPICE_DISPLAY(win->spice), seq); + spice_grab_sequence_free(seq); + g_free(str); + } + g_clear_error(&error); + + + state = g_key_file_get_boolean(keyfile, "ui", "toolbar", &error); + if (error == NULL) + gtk_widget_set_visible(win->toolbar, state); + g_clear_error(&error); + + state = g_key_file_get_boolean(keyfile, "ui", "statusbar", &error); + if (error == NULL) + gtk_widget_set_visible(win->statusbar, state); + g_clear_error(&error); +} + +/* ------------------------------------------------------------------ */ + +static const GtkActionEntry entries[] = { + { + .name = "FileMenu", + .label = "_File", + },{ + .name = "FileRecentMenu", + .label = "_Recent", + },{ + .name = "EditMenu", + .label = "_Edit", + },{ + .name = "ViewMenu", + .label = "_View", + },{ + .name = "InputMenu", + .label = "_Input", + },{ + .name = "OptionMenu", + .label = "_Options", + },{ + .name = "CompressionMenu", + .label = "_Preferred image compression", + },{ + .name = "HelpMenu", + .label = "_Help", + },{ + + /* File menu */ + .name = "Connect", + .stock_id = "_Connect", + .label = "_Connect ...", + .callback = G_CALLBACK(menu_cb_connect), + },{ + .name = "Close", + .stock_id = "window-close", + .label = "_Close", + .callback = G_CALLBACK(menu_cb_close), + .accelerator = "", /* none (disable default "W") */ + },{ + + /* Edit menu */ + .name = "CopyToGuest", + .stock_id = "edit-copy", + .label = "_Copy to guest", + .callback = G_CALLBACK(menu_cb_copy), + .accelerator = "", /* none (disable default "C") */ + },{ + .name = "PasteFromGuest", + .stock_id = "edit-paste", + .label = "_Paste from guest", + .callback = G_CALLBACK(menu_cb_paste), + .accelerator = "", /* none (disable default "V") */ + },{ + + /* View menu */ + .name = "Fullscreen", + .stock_id = "view-fullscreen", + .label = "_Fullscreen", + .callback = G_CALLBACK(menu_cb_fullscreen), + .accelerator = "F11", + },{ +#ifdef USE_SMARTCARD + .name = "InsertSmartcard", + .label = "_Insert Smartcard", + .callback = G_CALLBACK(menu_cb_insert_smartcard), + .accelerator = "F8", + },{ + .name = "RemoveSmartcard", + .label = "_Remove Smartcard", + .callback = G_CALLBACK(menu_cb_remove_smartcard), + .accelerator = "F9", + },{ +#endif + +#ifdef USE_USBREDIR + .name = "SelectUsbDevices", + .label = "_Select USB Devices for redirection", + .callback = G_CALLBACK(menu_cb_select_usb_devices), + .accelerator = "F10", + },{ +#endif + + .name = "MouseMode", + .label = "Toggle _mouse mode", + .callback = G_CALLBACK(menu_cb_mouse_mode), + .accelerator = "F7", + + },{ + /* Help menu */ + .name = "About", + .stock_id = "help-about", + .label = "_About ...", + .callback = G_CALLBACK(menu_cb_about), + } +}; + +static const char *spice_display_properties[] = { + "grab-keyboard", + "grab-mouse", + "resize-guest", + "scaling", + "disable-inputs", +}; + +static const char *spice_gtk_session_properties[] = { + "auto-clipboard", + "auto-usbredir", + "sync-modifiers", +}; + +static const GtkToggleActionEntry tentries[] = { + { + .name = "grab-keyboard", + .label = "Grab keyboard when active and focused", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "grab-mouse", + .label = "Grab mouse in server mode (no tabled/vdagent)", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "resize-guest", + .label = "Resize guest to match window size", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "scaling", + .label = "Scale display", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "disable-inputs", + .label = "Disable inputs", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "sync-modifiers", + .label = "Sync modifiers", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "auto-clipboard", + .label = "Automatic clipboard sharing between host and guest", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "auto-usbredir", + .label = "Auto redirect newly plugged in USB devices", + .callback = G_CALLBACK(menu_cb_bool_prop), + },{ + .name = "Statusbar", + .label = "Statusbar", + .callback = G_CALLBACK(menu_cb_statusbar), + },{ + .name = "Toolbar", + .label = "Toolbar", + .callback = G_CALLBACK(menu_cb_toolbar), + } +}; + +static const GtkRadioActionEntry compression_entries[] = { + { + .name = "auto-glz", + .label = "auto-glz", + .value = SPICE_IMAGE_COMPRESSION_AUTO_GLZ, + },{ + .name = "auto-lz", + .label = "auto-lz", + .value = SPICE_IMAGE_COMPRESSION_AUTO_LZ, + },{ + .name = "quic", + .label = "quic", + .value = SPICE_IMAGE_COMPRESSION_QUIC, + },{ + .name = "glz", + .label = "glz", + .value = SPICE_IMAGE_COMPRESSION_GLZ, + },{ + .name = "lz", + .label = "lz", + .value = SPICE_IMAGE_COMPRESSION_LZ, + },{ +#ifdef USE_LZ4 + .name = "lz4", + .label = "lz4", + .value = SPICE_IMAGE_COMPRESSION_LZ4, + },{ +#endif + .name = "off", + .label = "off", + .value = SPICE_IMAGE_COMPRESSION_OFF, + } +}; + +static char ui_xml[] = +"\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +#ifdef USE_SMARTCARD +" \n" +" \n" +#endif +#ifdef USE_USBREDIR +" \n" +#endif +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +#ifdef USE_LZ4 +" \n" +#endif +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n"; + +static gboolean is_gtk_session_property(const gchar *property) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS(spice_gtk_session_properties); i++) { + if (!strcmp(spice_gtk_session_properties[i], property)) { + return TRUE; + } + } + return FALSE; +} + +static void recent_item_activated_cb(GtkRecentChooser *chooser, gpointer data) +{ + GtkRecentInfo *info; + struct spice_connection *conn; + const char *uri; + + info = gtk_recent_chooser_get_current_item(chooser); + + uri = gtk_recent_info_get_uri(info); + g_return_if_fail(uri != NULL); + + conn = connection_new(); + g_object_set(conn->session, "uri", uri, NULL); + gtk_recent_info_unref(info); + connection_connect(conn); +} + +static void compression_cb(GtkRadioAction *action G_GNUC_UNUSED, + GtkRadioAction *current, + gpointer user_data) +{ + spice_display_change_preferred_compression(SPICE_CHANNEL(user_data), + gtk_radio_action_get_current_value(current)); +} + +static void +spice_window_class_init (SpiceWindowClass *klass) +{ +} + +static void +spice_window_init (SpiceWindow *self) +{ +} + +static SpiceWindow *create_spice_window(spice_connection *conn, SpiceChannel *channel, int id, gint monitor_id) +{ + char title[32]; + SpiceWindow *win; + GtkAction *toggle; + gboolean state; + GtkWidget *vbox, *frame; + GError *err = NULL; + int i; + SpiceGrabSequence *seq; + + win = g_object_new(SPICE_TYPE_WINDOW, NULL); + win->id = id; + win->monitor_id = monitor_id; + win->conn = conn; + win->display_channel = channel; + + /* toplevel */ + win->toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL); + if (spicy_title == NULL) { + snprintf(title, sizeof(title), "spice display %d:%d", id, monitor_id); + } else { + snprintf(title, sizeof(title), "%s", spicy_title); + } + + gtk_window_set_title(GTK_WINDOW(win->toplevel), title); + g_signal_connect(G_OBJECT(win->toplevel), "window-state-event", + G_CALLBACK(window_state_cb), win); + g_signal_connect(G_OBJECT(win->toplevel), "delete-event", + G_CALLBACK(delete_cb), win); + + /* menu + toolbar */ + win->ui = gtk_ui_manager_new(); + win->ag = gtk_action_group_new("MenuActions"); + gtk_action_group_add_actions(win->ag, entries, G_N_ELEMENTS(entries), win); + gtk_action_group_add_toggle_actions(win->ag, tentries, + G_N_ELEMENTS(tentries), win); + gtk_action_group_add_radio_actions(win->ag, compression_entries, + G_N_ELEMENTS(compression_entries), -1, + G_CALLBACK(compression_cb), win->display_channel); + if (!spice_channel_test_capability(win->display_channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION)) { + GtkAction *compression_menu_action = gtk_action_group_get_action(win->ag, "CompressionMenu"); + gtk_action_set_sensitive(compression_menu_action, FALSE); + } + gtk_ui_manager_insert_action_group(win->ui, win->ag, 0); + gtk_window_add_accel_group(GTK_WINDOW(win->toplevel), + gtk_ui_manager_get_accel_group(win->ui)); + + err = NULL; + if (!gtk_ui_manager_add_ui_from_string(win->ui, ui_xml, -1, &err)) { + g_warning("building menus failed: %s", err->message); + g_error_free(err); + exit(1); + } + win->menubar = gtk_ui_manager_get_widget(win->ui, "/MainMenu"); + win->toolbar = gtk_ui_manager_get_widget(win->ui, "/ToolBar"); + + /* recent menu */ + win->ritem = gtk_ui_manager_get_widget + (win->ui, "/MainMenu/FileMenu/FileRecentMenu"); + + GtkRecentFilter *rfilter; + + win->rmenu = gtk_recent_chooser_menu_new(); + gtk_recent_chooser_set_show_icons(GTK_RECENT_CHOOSER(win->rmenu), FALSE); + rfilter = gtk_recent_filter_new(); + gtk_recent_filter_add_mime_type(rfilter, "application/x-spice"); + gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(win->rmenu), rfilter); + gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(win->rmenu), FALSE); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->ritem), win->rmenu); + g_signal_connect(win->rmenu, "item-activated", + G_CALLBACK(recent_item_activated_cb), win); + + /* spice display */ + win->spice = GTK_WIDGET(spice_display_new_with_monitor(conn->session, id, monitor_id)); + seq = spice_grab_sequence_new_from_string("Shift_L+F12"); + spice_display_set_grab_keys(SPICE_DISPLAY(win->spice), seq); + spice_grab_sequence_free(seq); + + g_signal_connect(G_OBJECT(win->spice), "mouse-grab", + G_CALLBACK(mouse_grab_cb), win); + g_signal_connect(G_OBJECT(win->spice), "keyboard-grab", + G_CALLBACK(keyboard_grab_cb), win); + g_signal_connect(G_OBJECT(win->spice), "grab-keys-pressed", + G_CALLBACK(grab_keys_pressed_cb), win); + + /* status line */ + win->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1); + + win->status = gtk_label_new("status line"); + gtk_misc_set_alignment(GTK_MISC(win->status), 0, 0.5); + gtk_misc_set_padding(GTK_MISC(win->status), 3, 1); + update_status_window(win); + + frame = gtk_frame_new(NULL); + gtk_box_pack_start(GTK_BOX(win->statusbar), frame, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(frame), win->status); + + for (i = 0; i < STATE_MAX; i++) { + win->st[i] = gtk_label_new("?"); + gtk_label_set_width_chars(GTK_LABEL(win->st[i]), 5); + frame = gtk_frame_new(NULL); + gtk_box_pack_end(GTK_BOX(win->statusbar), frame, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(frame), win->st[i]); + } + + /* Make a vbox and put stuff in */ + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); + gtk_container_add(GTK_CONTAINER(win->toplevel), vbox); + gtk_box_pack_start(GTK_BOX(vbox), win->menubar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), win->toolbar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), win->spice, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), win->statusbar, FALSE, TRUE, 0); + + /* show window */ + if (fullscreen) + gtk_window_fullscreen(GTK_WINDOW(win->toplevel)); + + gtk_widget_show_all(vbox); + restore_configuration(win); + + /* init toggle actions */ + for (i = 0; i < G_N_ELEMENTS(spice_display_properties); i++) { + toggle = gtk_action_group_get_action(win->ag, + spice_display_properties[i]); + g_object_get(win->spice, spice_display_properties[i], &state, NULL); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggle), state); + } + + for (i = 0; i < G_N_ELEMENTS(spice_gtk_session_properties); i++) { + char notify[64]; + + toggle = gtk_action_group_get_action(win->ag, + spice_gtk_session_properties[i]); + g_object_get(win->conn->gtk_session, spice_gtk_session_properties[i], + &state, NULL); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggle), state); + + snprintf(notify, sizeof(notify), "notify::%s", + spice_gtk_session_properties[i]); + spice_g_signal_connect_object(win->conn->gtk_session, notify, + G_CALLBACK(menu_cb_conn_bool_prop_changed), + win, 0); + } + + update_edit_menu_window(win); + + toggle = gtk_action_group_get_action(win->ag, "Toolbar"); + state = gtk_widget_get_visible(win->toolbar); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggle), state); + + toggle = gtk_action_group_get_action(win->ag, "Statusbar"); + state = gtk_widget_get_visible(win->statusbar); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggle), state); + +#ifdef USE_SMARTCARD + gboolean smartcard; + + enable_smartcard_actions(win, NULL, FALSE, FALSE); + g_object_get(G_OBJECT(conn->session), + "enable-smartcard", &smartcard, + NULL); + if (smartcard) { + g_signal_connect(G_OBJECT(spice_smartcard_manager_get()), "reader-added", + (GCallback)reader_added_cb, win); + g_signal_connect(G_OBJECT(spice_smartcard_manager_get()), "reader-removed", + (GCallback)reader_removed_cb, win); + g_signal_connect(G_OBJECT(spice_smartcard_manager_get()), "card-inserted", + (GCallback)card_inserted_cb, win); + g_signal_connect(G_OBJECT(spice_smartcard_manager_get()), "card-removed", + (GCallback)card_removed_cb, win); + } +#endif + +#ifndef USE_USBREDIR + GtkAction *usbredir = gtk_action_group_get_action(win->ag, "auto-usbredir"); + gtk_action_set_visible(usbredir, FALSE); +#endif + + gtk_widget_grab_focus(win->spice); + + return win; +} + +static void destroy_spice_window(SpiceWindow *win) +{ + if (win == NULL) + return; + + SPICE_DEBUG("destroy window (#%d:%d)", win->id, win->monitor_id); + g_object_unref(win->ag); + g_object_unref(win->ui); + gtk_widget_destroy(win->toplevel); + g_object_unref(win); +} + +/* ------------------------------------------------------------------ */ + +static void recent_add(SpiceSession *session) +{ + GtkRecentManager *recent; + GtkRecentData meta = { + .mime_type = (char*)"application/x-spice", + .app_name = (char*)"spicy", + .app_exec = (char*)"spicy --uri=%u", + }; + char *uri; + + g_object_get(session, "uri", &uri, NULL); + SPICE_DEBUG("%s: %s", __FUNCTION__, uri); + + recent = gtk_recent_manager_get_default(); + if (g_str_has_prefix(uri, "spice://")) + meta.display_name = uri + 8; + else if (g_str_has_prefix(uri, "spice+unix://")) + meta.display_name = uri + 13; + else + g_return_if_reached(); + + if (!gtk_recent_manager_add_full(recent, uri, &meta)) + g_warning("Recent item couldn't be added successfully"); + + g_free(uri); +} + +static void main_channel_event(SpiceChannel *channel, SpiceChannelEvent event, + gpointer data) +{ + const GError *error = NULL; + spice_connection *conn = data; + char password[64]; + int rc; + + switch (event) { + case SPICE_CHANNEL_OPENED: + g_message("main channel: opened"); + recent_add(conn->session); + break; + case SPICE_CHANNEL_SWITCHING: + g_message("main channel: switching host"); + break; + case SPICE_CHANNEL_CLOSED: + /* this event is only sent if the channel was succesfully opened before */ + g_message("main channel: closed"); + connection_disconnect(conn); + break; + case SPICE_CHANNEL_ERROR_IO: + connection_disconnect(conn); + break; + case SPICE_CHANNEL_ERROR_TLS: + case SPICE_CHANNEL_ERROR_LINK: + case SPICE_CHANNEL_ERROR_CONNECT: + error = spice_channel_get_error(channel); + g_message("main channel: failed to connect"); + if (error) { + g_message("channel error: %s", error->message); + } + + if (spicy_connect_dialog(conn->session)) { + connection_connect(conn); + } else { + connection_disconnect(conn); + } + break; + case SPICE_CHANNEL_ERROR_AUTH: + g_warning("main channel: auth failure (wrong password?)"); + strcpy(password, ""); + /* FIXME i18 */ + rc = ask_user(NULL, "Authentication", + "Please enter the spice server password", + password, sizeof(password), true); + if (rc == 0) { + g_object_set(conn->session, "password", password, NULL); + connection_connect(conn); + } else { + connection_disconnect(conn); + } + break; + default: + /* TODO: more sophisticated error handling */ + g_warning("unknown main channel event: %u", event); + /* connection_disconnect(conn); */ + break; + } +} + +static void main_mouse_update(SpiceChannel *channel, gpointer data) +{ + spice_connection *conn = data; + gint mode; + + g_object_get(channel, "mouse-mode", &mode, NULL); + switch (mode) { + case SPICE_MOUSE_MODE_SERVER: + conn->mouse_state = "server"; + break; + case SPICE_MOUSE_MODE_CLIENT: + conn->mouse_state = "client"; + break; + default: + conn->mouse_state = "?"; + break; + } + update_status(conn); +} + +static void main_agent_update(SpiceChannel *channel, gpointer data) +{ + spice_connection *conn = data; + + g_object_get(channel, "agent-connected", &conn->agent_connected, NULL); + conn->agent_state = conn->agent_connected ? "yes" : "no"; + update_status(conn); + update_edit_menu(conn); +} + +static void inputs_modifiers(SpiceChannel *channel, gpointer data) +{ + spice_connection *conn = data; + int m, i; + + g_object_get(channel, "key-modifiers", &m, NULL); + for (i = 0; i < SPICE_N_ELEMENTS(conn->wins); i++) { + if (conn->wins[i] == NULL) + continue; + + gtk_label_set_text(GTK_LABEL(conn->wins[i]->st[STATE_SCROLL_LOCK]), + m & SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK ? "SCROLL" : ""); + gtk_label_set_text(GTK_LABEL(conn->wins[i]->st[STATE_CAPS_LOCK]), + m & SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK ? "CAPS" : ""); + gtk_label_set_text(GTK_LABEL(conn->wins[i]->st[STATE_NUM_LOCK]), + m & SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK ? "NUM" : ""); + } +} + +static void display_mark(SpiceChannel *channel, gint mark, SpiceWindow *win) +{ + g_return_if_fail(win != NULL); + g_return_if_fail(win->toplevel != NULL); + + if (mark == TRUE) { + gtk_widget_show(win->toplevel); + } else { + gtk_widget_hide(win->toplevel); + } +} + +static void update_auto_usbredir_sensitive(spice_connection *conn) +{ +#ifdef USE_USBREDIR + int i; + GtkAction *ac; + gboolean sensitive; + + sensitive = spice_session_has_channel_type(conn->session, + SPICE_CHANNEL_USBREDIR); + for (i = 0; i < SPICE_N_ELEMENTS(conn->wins); i++) { + if (conn->wins[i] == NULL) + continue; + ac = gtk_action_group_get_action(conn->wins[i]->ag, "auto-usbredir"); + gtk_action_set_sensitive(ac, sensitive); + } +#endif +} + +static SpiceWindow* get_window(spice_connection *conn, int channel_id, int monitor_id) +{ + g_return_val_if_fail(channel_id < CHANNELID_MAX, NULL); + g_return_val_if_fail(monitor_id < MONITORID_MAX, NULL); + + return conn->wins[channel_id * CHANNELID_MAX + monitor_id]; +} + +static void add_window(spice_connection *conn, SpiceWindow *win) +{ + g_return_if_fail(win != NULL); + g_return_if_fail(win->id < CHANNELID_MAX); + g_return_if_fail(win->monitor_id < MONITORID_MAX); + g_return_if_fail(conn->wins[win->id * CHANNELID_MAX + win->monitor_id] == NULL); + + SPICE_DEBUG("add display monitor %d:%d", win->id, win->monitor_id); + conn->wins[win->id * CHANNELID_MAX + win->monitor_id] = win; +} + +static void del_window(spice_connection *conn, SpiceWindow *win) +{ + if (win == NULL) + return; + + g_return_if_fail(win->id < CHANNELID_MAX); + g_return_if_fail(win->monitor_id < MONITORID_MAX); + + g_debug("del display monitor %d:%d", win->id, win->monitor_id); + conn->wins[win->id * CHANNELID_MAX + win->monitor_id] = NULL; + if (win->id > 0) + spice_main_set_display_enabled(conn->main, win->id, FALSE); + else + spice_main_set_display_enabled(conn->main, win->monitor_id, FALSE); + spice_main_send_monitor_config(conn->main); + + destroy_spice_window(win); +} + +static void display_monitors(SpiceChannel *display, GParamSpec *pspec, + spice_connection *conn) +{ + GArray *monitors = NULL; + int id; + guint i; + + g_object_get(display, + "channel-id", &id, + "monitors", &monitors, + NULL); + g_return_if_fail(monitors != NULL); + + for (i = 0; i < monitors->len; i++) { + SpiceWindow *w; + + if (!get_window(conn, id, i)) { + w = create_spice_window(conn, display, id, i); + add_window(conn, w); + spice_g_signal_connect_object(display, "display-mark", + G_CALLBACK(display_mark), w, 0); + gtk_widget_show(w->toplevel); + update_auto_usbredir_sensitive(conn); + } + } + + for (; i < MONITORID_MAX; i++) + del_window(conn, get_window(conn, id, i)); + + g_clear_pointer(&monitors, g_array_unref); +} + +static void port_write_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpicePortChannel *port = SPICE_PORT_CHANNEL(source_object); + GError *error = NULL; + + spice_port_write_finish(port, res, &error); + if (error != NULL) + g_warning("%s", error->message); + g_clear_error(&error); +} + +static void port_flushed_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + SpiceChannel *channel = SPICE_CHANNEL(source_object); + GError *error = NULL; + + spice_channel_flush_finish(channel, res, &error); + if (error != NULL) + g_warning("%s", error->message); + g_clear_error(&error); + + spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED); +} + +static gboolean input_cb(GIOChannel *gin, GIOCondition condition, gpointer data) +{ + char buf[4096]; + gsize bytes_read; + GIOStatus status; + + if (!(condition & G_IO_IN)) + return FALSE; + + status = g_io_channel_read_chars(gin, buf, sizeof(buf), &bytes_read, NULL); + if (status != G_IO_STATUS_NORMAL) + return FALSE; + + if (stdin_port != NULL) + spice_port_write_async(stdin_port, buf, bytes_read, NULL, port_write_cb, NULL); + + return TRUE; +} + +static void port_opened(SpiceChannel *channel, GParamSpec *pspec, + spice_connection *conn) +{ + SpicePortChannel *port = SPICE_PORT_CHANNEL(channel); + gchar *name = NULL; + gboolean opened = FALSE; + + g_object_get(channel, + "port-name", &name, + "port-opened", &opened, + NULL); + + g_printerr("port %p %s: %s\n", channel, name, opened ? "opened" : "closed"); + + if (opened) { + /* only send a break event and disconnect */ + if (g_strcmp0(name, "org.spice.spicy.break") == 0) { + spice_port_event(port, SPICE_PORT_EVENT_BREAK); + spice_channel_flush_async(channel, NULL, port_flushed_cb, conn); + } + + /* handle the first spicy port and connect it to stdin/out */ + if (g_strcmp0(name, "org.spice.spicy") == 0 && stdin_port == NULL) { + stdin_port = port; + } + } else { + if (port == stdin_port) + stdin_port = NULL; + } + + g_free(name); +} + +static void port_data(SpicePortChannel *port, + gpointer data, int size, spice_connection *conn) +{ + int r; + + if (port != stdin_port) + return; + + r = write(fileno(stdout), data, size); + if (r != size) { + g_warning("port write failed result %d/%d errno %d", r, size, errno); + } +} + +typedef struct { + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *progress; + GtkWidget *label; + GtkWidget *cancel; +} TransferTaskWidgets; + +static void transfer_update_progress(GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + spice_connection *conn = user_data; + TransferTaskWidgets *widgets = g_hash_table_lookup(conn->transfers, object); + g_return_if_fail(widgets); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(widgets->progress), + spice_file_transfer_task_get_progress(SPICE_FILE_TRANSFER_TASK(object))); +} + +static void transfer_task_finished(SpiceFileTransferTask *task, GError *error, spice_connection *conn) +{ + if (error) + g_warning("%s", error->message); + g_hash_table_remove(conn->transfers, task); + if (!g_hash_table_size(conn->transfers)) + gtk_widget_hide(conn->transfer_dialog); +} + +static void dialog_response_cb(GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + spice_connection *conn = user_data; + g_print("Reponse: %i\n", response_id); + + if (response_id == GTK_RESPONSE_CANCEL) { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, conn->transfers); + while (g_hash_table_iter_next(&iter, &key, &value)) { + SpiceFileTransferTask *task = key; + spice_file_transfer_task_cancel(task); + } + } +} + +static void +task_cancel_cb(GtkButton *button, + gpointer user_data) +{ + SpiceFileTransferTask *task = SPICE_FILE_TRANSFER_TASK(user_data); + spice_file_transfer_task_cancel(task); +} + +static TransferTaskWidgets * +transfer_task_widgets_new(SpiceFileTransferTask *task) +{ + TransferTaskWidgets *widgets = g_new0(TransferTaskWidgets, 1); + + widgets->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + widgets->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); + widgets->cancel = gtk_button_new_with_label("Cancel"); + + widgets->progress = gtk_progress_bar_new(); + widgets->label = gtk_label_new(spice_file_transfer_task_get_filename(task)); + + gtk_widget_set_halign(widgets->label, GTK_ALIGN_START); + gtk_widget_set_valign(widgets->label, GTK_ALIGN_BASELINE); + gtk_widget_set_valign(widgets->progress, GTK_ALIGN_CENTER); + gtk_widget_set_hexpand(widgets->progress, TRUE); + gtk_widget_set_valign(widgets->cancel, GTK_ALIGN_CENTER); + gtk_widget_set_hexpand(widgets->progress, FALSE); + + gtk_box_pack_start(GTK_BOX(widgets->hbox), widgets->progress, + TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(widgets->hbox), widgets->cancel, + FALSE, TRUE, 0); + + gtk_box_pack_start(GTK_BOX(widgets->vbox), widgets->label, + TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(widgets->vbox), widgets->hbox, + TRUE, TRUE, 0); + + g_signal_connect(widgets->cancel, "clicked", + G_CALLBACK(task_cancel_cb), task); + + gtk_widget_show_all(widgets->vbox); + + return widgets; +} + +static void +transfer_task_widgets_free(TransferTaskWidgets *widgets) +{ + /* child widgets will be destroyed automatically */ + gtk_widget_destroy(widgets->vbox); + g_free(widgets); +} + +static void spice_connection_add_task(spice_connection *conn, SpiceFileTransferTask *task) +{ + TransferTaskWidgets *widgets; + GtkWidget *content = NULL; + + g_signal_connect(task, "notify::progress", + G_CALLBACK(transfer_update_progress), conn); + g_signal_connect(task, "finished", + G_CALLBACK(transfer_task_finished), conn); + if (!conn->transfer_dialog) { + conn->transfer_dialog = gtk_dialog_new_with_buttons("File Transfers", + GTK_WINDOW(conn->wins[0]->toplevel), 0, + "Cancel", GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(conn->transfer_dialog), + GTK_RESPONSE_CANCEL); + gtk_window_set_resizable(GTK_WINDOW(conn->transfer_dialog), FALSE); + g_signal_connect(conn->transfer_dialog, "response", + G_CALLBACK(dialog_response_cb), conn); + } + gtk_widget_show(conn->transfer_dialog); + content = gtk_dialog_get_content_area(GTK_DIALOG(conn->transfer_dialog)); + gtk_container_set_border_width(GTK_CONTAINER(content), 12); + + widgets = transfer_task_widgets_new(task); + g_hash_table_insert(conn->transfers, g_object_ref(task), widgets); + gtk_box_pack_start(GTK_BOX(content), + widgets->vbox, TRUE, TRUE, 6); +} + +static void new_file_transfer(SpiceMainChannel *main, SpiceFileTransferTask *task, gpointer user_data) +{ + spice_connection *conn = user_data; + g_debug("new file transfer task"); + spice_connection_add_task(conn, task); +} + +static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data) +{ + spice_connection *conn = data; + int id; + + g_object_get(channel, "channel-id", &id, NULL); + conn->channels++; + SPICE_DEBUG("new channel (#%d)", id); + + if (SPICE_IS_MAIN_CHANNEL(channel)) { + SPICE_DEBUG("new main channel"); + conn->main = SPICE_MAIN_CHANNEL(channel); + g_signal_connect(channel, "channel-event", + G_CALLBACK(main_channel_event), conn); + g_signal_connect(channel, "main-mouse-update", + G_CALLBACK(main_mouse_update), conn); + g_signal_connect(channel, "main-agent-update", + G_CALLBACK(main_agent_update), conn); + g_signal_connect(channel, "new-file-transfer", + G_CALLBACK(new_file_transfer), conn); + main_mouse_update(channel, conn); + main_agent_update(channel, conn); + } + + if (SPICE_IS_DISPLAY_CHANNEL(channel)) { + if (id >= SPICE_N_ELEMENTS(conn->wins)) + return; + if (conn->wins[id] != NULL) + return; + SPICE_DEBUG("new display channel (#%d)", id); + g_signal_connect(channel, "notify::monitors", + G_CALLBACK(display_monitors), conn); + spice_channel_connect(channel); + } + + if (SPICE_IS_INPUTS_CHANNEL(channel)) { + SPICE_DEBUG("new inputs channel"); + g_signal_connect(channel, "inputs-modifiers", + G_CALLBACK(inputs_modifiers), conn); + } + + if (SPICE_IS_PLAYBACK_CHANNEL(channel)) { + SPICE_DEBUG("new audio channel"); + conn->audio = spice_audio_get(s, NULL); + } + + if (SPICE_IS_USBREDIR_CHANNEL(channel)) { + update_auto_usbredir_sensitive(conn); + } + + if (SPICE_IS_PORT_CHANNEL(channel)) { + g_signal_connect(channel, "notify::port-opened", + G_CALLBACK(port_opened), conn); + g_signal_connect(channel, "port-data", + G_CALLBACK(port_data), conn); + spice_channel_connect(channel); + } +} + +static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data) +{ + spice_connection *conn = data; + int id; + + g_object_get(channel, "channel-id", &id, NULL); + if (SPICE_IS_MAIN_CHANNEL(channel)) { + SPICE_DEBUG("zap main channel"); + conn->main = NULL; + } + + if (SPICE_IS_DISPLAY_CHANNEL(channel)) { + if (id >= SPICE_N_ELEMENTS(conn->wins)) + return; + SPICE_DEBUG("zap display channel (#%d)", id); + /* FIXME destroy widget only */ + } + + if (SPICE_IS_PLAYBACK_CHANNEL(channel)) { + SPICE_DEBUG("zap audio channel"); + } + + if (SPICE_IS_USBREDIR_CHANNEL(channel)) { + update_auto_usbredir_sensitive(conn); + } + + if (SPICE_IS_PORT_CHANNEL(channel)) { + if (SPICE_PORT_CHANNEL(channel) == stdin_port) + stdin_port = NULL; + } + + conn->channels--; + if (conn->channels > 0) { + return; + } + + connection_destroy(conn); +} + +static void migration_state(GObject *session, + GParamSpec *pspec, gpointer data) +{ + SpiceSessionMigration mig; + + g_object_get(session, "migration-state", &mig, NULL); + if (mig == SPICE_SESSION_MIGRATION_SWITCHING) + g_message("migrating session"); +} + +static spice_connection *connection_new(void) +{ + spice_connection *conn; + SpiceUsbDeviceManager *manager; + + conn = g_new0(spice_connection, 1); + conn->session = spice_session_new(); + conn->gtk_session = spice_gtk_session_get(conn->session); + g_signal_connect(conn->session, "channel-new", + G_CALLBACK(channel_new), conn); + g_signal_connect(conn->session, "channel-destroy", + G_CALLBACK(channel_destroy), conn); + g_signal_connect(conn->session, "notify::migration-state", + G_CALLBACK(migration_state), conn); + + manager = spice_usb_device_manager_get(conn->session, NULL); + if (manager) { + g_signal_connect(manager, "auto-connect-failed", + G_CALLBACK(usb_connect_failed), NULL); + g_signal_connect(manager, "device-error", + G_CALLBACK(usb_connect_failed), NULL); + } + + conn->transfers = g_hash_table_new_full(g_direct_hash, g_direct_equal, + g_object_unref, + (GDestroyNotify)transfer_task_widgets_free); + connections++; + SPICE_DEBUG("%s (%d)", __FUNCTION__, connections); + return conn; +} + +static void connection_connect(spice_connection *conn) +{ + conn->disconnecting = false; + spice_session_connect(conn->session); +} + +static void connection_disconnect(spice_connection *conn) +{ + if (conn->disconnecting) + return; + conn->disconnecting = true; + spice_session_disconnect(conn->session); +} + +static void connection_destroy(spice_connection *conn) +{ + g_object_unref(conn->session); + g_hash_table_unref(conn->transfers); + free(conn); + + connections--; + SPICE_DEBUG("%s (%d)", __FUNCTION__, connections); + if (connections > 0) { + return; + } + + g_main_loop_quit(mainloop); +} + +/* ------------------------------------------------------------------ */ + +static GOptionEntry cmd_entries[] = { + { + .long_name = "full-screen", + .short_name = 'f', + .arg = G_OPTION_ARG_NONE, + .arg_data = &fullscreen, + .description = "Open in full screen mode", + },{ + .long_name = "version", + .arg = G_OPTION_ARG_NONE, + .arg_data = &version, + .description = "Display version and quit", + },{ + .long_name = "title", + .arg = G_OPTION_ARG_STRING, + .arg_data = &spicy_title, + .description = "Set the window title", + .arg_description = "", + },{ + /* end of list */ + } +}; + +static void usb_connect_failed(GObject *object, + SpiceUsbDevice *device, + GError *error, + gpointer data) +{ + GtkWidget *dialog; + + if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED) + return; + + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "USB redirection error"); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + "%s", error->message); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +static void setup_terminal(gboolean reset) +{ + int stdinfd = fileno(stdin); + + if (!isatty(stdinfd)) + return; + +#ifdef HAVE_TERMIOS_H + static struct termios saved_tios; + struct termios tios; + + if (reset) + tios = saved_tios; + else { + tcgetattr(stdinfd, &tios); + saved_tios = tios; + tios.c_lflag &= ~(ICANON | ECHO); + } + + tcsetattr(stdinfd, TCSANOW, &tios); +#endif +} + +static void watch_stdin(void) +{ + int stdinfd = fileno(stdin); + GIOChannel *gin; + + setup_terminal(false); + gin = g_io_channel_unix_new(stdinfd); + g_io_channel_set_flags(gin, G_IO_FLAG_NONBLOCK, NULL); + g_io_add_watch(gin, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, input_cb, NULL); +} + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + spice_connection *conn; + gchar *conf_file, *conf; + char *host = NULL, *port = NULL, *tls_port = NULL, *unix_path = NULL; + + keyfile = g_key_file_new(); + + int mode = S_IRWXU; + conf_file = g_build_filename(g_get_user_config_dir(), "spicy", NULL); + if (g_mkdir_with_parents(conf_file, mode) == -1) + SPICE_DEBUG("failed to create config directory"); + g_free(conf_file); + + conf_file = g_build_filename(g_get_user_config_dir(), "spicy", "settings", NULL); + if (!g_key_file_load_from_file(keyfile, conf_file, + G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, &error)) { + SPICE_DEBUG("Couldn't load configuration: %s", error->message); + g_clear_error(&error); + } + + /* parse opts */ + gtk_init(&argc, &argv); + context = g_option_context_new("- spice client test application"); + g_option_context_set_summary(context, "Gtk+ test client to connect to Spice servers."); + g_option_context_set_description(context, "Report bugs to " PACKAGE_BUGREPORT "."); + g_option_context_add_group(context, spice_get_option_group()); + g_option_context_set_main_group(context, spice_cmdline_get_option_group()); + g_option_context_add_main_entries(context, cmd_entries, NULL); + g_option_context_add_group(context, gtk_get_option_group(TRUE)); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print("option parsing failed: %s\n", error->message); + exit(1); + } + g_option_context_free(context); + + if (version) { + g_print("spicy " PACKAGE_VERSION "\n"); + exit(0); + } + + mainloop = g_main_loop_new(NULL, false); + + conn = connection_new(); + spice_set_session_option(conn->session); + spice_cmdline_session_setup(conn->session); + + g_object_get(conn->session, + "unix-path", &unix_path, + "host", &host, + "port", &port, + "tls-port", &tls_port, + NULL); + /* If user doesn't provide hostname and port, show the dialog window + instead of connecting to server automatically */ + if ((host == NULL || (port == NULL && tls_port == NULL)) && unix_path == NULL) { + if (!spicy_connect_dialog(conn->session)) { + exit(0); + } + } + g_free(host); + g_free(port); + g_free(tls_port); + g_free(unix_path); + + watch_stdin(); + + connection_connect(conn); + if (connections > 0) + g_main_loop_run(mainloop); + g_main_loop_unref(mainloop); + + if ((conf = g_key_file_to_data(keyfile, NULL, &error)) == NULL || + !g_file_set_contents(conf_file, conf, -1, &error)) { + SPICE_DEBUG("Couldn't save configuration: %s", error->message); + g_error_free(error); + error = NULL; + } + + g_free(conf_file); + g_free(conf); + g_key_file_free(keyfile); + + g_free(spicy_title); + + setup_terminal(true); + return 0; +} diff --git a/src/usb-acl-helper.c b/src/usb-acl-helper.c new file mode 100644 index 0000000..fa845be --- /dev/null +++ b/src/usb-acl-helper.c @@ -0,0 +1,284 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "usb-acl-helper.h" + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_USB_ACL_HELPER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_USB_ACL_HELPER, SpiceUsbAclHelperPrivate)) + +struct _SpiceUsbAclHelperPrivate { + GTask *task; + GIOChannel *in_ch; + GIOChannel *out_ch; + GCancellable *cancellable; + gulong cancellable_id; +}; + +G_DEFINE_TYPE(SpiceUsbAclHelper, spice_usb_acl_helper, G_TYPE_OBJECT); + +static void spice_usb_acl_helper_init(SpiceUsbAclHelper *self) +{ + self->priv = SPICE_USB_ACL_HELPER_GET_PRIVATE(self); +} + +static void spice_usb_acl_helper_cleanup(SpiceUsbAclHelper *self) +{ + SpiceUsbAclHelperPrivate *priv = self->priv; + + g_cancellable_disconnect(priv->cancellable, priv->cancellable_id); + priv->cancellable = NULL; + priv->cancellable_id = 0; + + g_clear_object(&priv->task); + + g_clear_pointer(&priv->in_ch, g_io_channel_unref); + g_clear_pointer(&priv->out_ch, g_io_channel_unref); +} + +static void spice_usb_acl_helper_finalize(GObject *gobject) +{ + spice_usb_acl_helper_cleanup(SPICE_USB_ACL_HELPER(gobject)); + + if (G_OBJECT_CLASS(spice_usb_acl_helper_parent_class)->finalize) + G_OBJECT_CLASS(spice_usb_acl_helper_parent_class)->finalize(gobject); +} + +static void spice_usb_acl_helper_class_init(SpiceUsbAclHelperClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = spice_usb_acl_helper_finalize; + + g_type_class_add_private(klass, sizeof(SpiceUsbAclHelperPrivate)); +} + +/* ------------------------------------------------------------------ */ +/* callbacks */ + +static void async_result_set_cancelled(GTask *task) +{ + g_task_return_new_error(task, + G_IO_ERROR, G_IO_ERROR_CANCELLED, + "Setting USB device node ACL cancelled"); +} + +static gboolean cb_out_watch(GIOChannel *channel, + GIOCondition cond, + gpointer *user_data) +{ + SpiceUsbAclHelper *self = SPICE_USB_ACL_HELPER(user_data); + SpiceUsbAclHelperPrivate *priv = self->priv; + gboolean success = FALSE; + GError *err = NULL; + GIOStatus status; + gchar *string; + gsize size; + + /* Check that we've not been cancelled */ + if (priv->task == NULL) + goto done; + + g_return_val_if_fail(channel == priv->out_ch, FALSE); + + status = g_io_channel_read_line(priv->out_ch, &string, &size, NULL, &err); + switch (status) { + case G_IO_STATUS_NORMAL: + string[strlen(string) - 1] = 0; + if (!strcmp(string, "SUCCESS")) { + success = TRUE; + g_task_return_boolean(priv->task, TRUE); + } else if (!strcmp(string, "CANCELED")) { + async_result_set_cancelled(priv->task); + } else { + g_task_return_new_error(priv->task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error setting USB device node ACL: '%s'", + string); + } + g_free(string); + break; + case G_IO_STATUS_ERROR: + g_task_return_error(priv->task, err); + break; + case G_IO_STATUS_EOF: + g_task_return_new_error(priv->task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Unexpected EOF reading from acl helper stdout"); + break; + case G_IO_STATUS_AGAIN: + return TRUE; /* Wait for more input */ + } + + g_cancellable_disconnect(priv->cancellable, priv->cancellable_id); + priv->cancellable = NULL; + priv->cancellable_id = 0; + + g_clear_object(&priv->task); + + if (!success) + spice_usb_acl_helper_cleanup(self); + +done: + g_object_unref(self); + return FALSE; +} + +static void cancelled_cb(GCancellable *cancellable, gpointer user_data) +{ + SpiceUsbAclHelper *self = SPICE_USB_ACL_HELPER(user_data); + + spice_usb_acl_helper_cancel(self); +} + +static void helper_child_watch_cb(GPid pid, gint status, gpointer user_data) +{ + /* Nothing to do, but we need the child watch to avoid zombies */ +} + +/* ------------------------------------------------------------------ */ +/* private api */ + +G_GNUC_INTERNAL +SpiceUsbAclHelper *spice_usb_acl_helper_new(void) +{ + GObject *obj; + + obj = g_object_new(SPICE_TYPE_USB_ACL_HELPER, NULL); + + return SPICE_USB_ACL_HELPER(obj); +} + +G_GNUC_INTERNAL +void spice_usb_acl_helper_open_acl_async(SpiceUsbAclHelper *self, + gint busnum, gint devnum, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_USB_ACL_HELPER(self)); + + SpiceUsbAclHelperPrivate *priv = self->priv; + GTask *task; + GError *err = NULL; + GIOStatus status; + GPid helper_pid; + gsize bytes_written; + const gchar *acl_helper = g_getenv("SPICE_USB_ACL_BINARY"); + if (acl_helper == NULL) + acl_helper = ACL_HELPER_PATH"/spice-client-glib-usb-acl-helper"; + gchar *argv[] = { (char*)acl_helper, NULL }; + gint in, out; + gchar buf[128]; + + task = g_task_new(self, cancellable, callback, user_data); + + if (priv->out_ch) { + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error acl-helper already has an acl open"); + goto done; + } + + if (g_cancellable_set_error_if_cancelled(cancellable, &err)) { + g_task_return_error(task, err); + goto done; + } + + if (!g_spawn_async_with_pipes(NULL, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, + NULL, NULL, &helper_pid, &in, &out, NULL, &err)) { + g_task_return_error(task, err); + goto done; + } + g_child_watch_add(helper_pid, helper_child_watch_cb, NULL); + + priv->in_ch = g_io_channel_unix_new(in); + g_io_channel_set_close_on_unref(priv->in_ch, TRUE); + + priv->out_ch = g_io_channel_unix_new(out); + g_io_channel_set_close_on_unref(priv->out_ch, TRUE); + status = g_io_channel_set_flags(priv->out_ch, G_IO_FLAG_NONBLOCK, &err); + if (status != G_IO_STATUS_NORMAL) { + g_task_return_error(task, err); + goto done; + } + + snprintf(buf, sizeof(buf), "%d %d\n", busnum, devnum); + status = g_io_channel_write_chars(priv->in_ch, buf, -1, + &bytes_written, &err); + if (status != G_IO_STATUS_NORMAL) { + g_task_return_error(task, err); + goto done; + } + status = g_io_channel_flush(priv->in_ch, &err); + if (status != G_IO_STATUS_NORMAL) { + g_task_return_error(task, err); + goto done; + } + + priv->task = task; + if (cancellable) { + priv->cancellable = cancellable; + priv->cancellable_id = g_cancellable_connect(cancellable, + G_CALLBACK(cancelled_cb), + self, NULL); + } + g_io_add_watch(priv->out_ch, G_IO_IN|G_IO_HUP, + (GIOFunc)cb_out_watch, g_object_ref(self)); + return; + +done: + spice_usb_acl_helper_cleanup(self); + g_object_unref(task); +} + +G_GNUC_INTERNAL +gboolean spice_usb_acl_helper_open_acl_finish( + SpiceUsbAclHelper *self, GAsyncResult *res, GError **err) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, self), + FALSE); + + return g_task_propagate_boolean(task, err); +} + +G_GNUC_INTERNAL +void spice_usb_acl_helper_cancel(SpiceUsbAclHelper *self) +{ + g_return_if_fail(SPICE_IS_USB_ACL_HELPER(self)); + + SpiceUsbAclHelperPrivate *priv = self->priv; + g_return_if_fail(priv->task != NULL); + + async_result_set_cancelled(priv->task); + g_clear_object(&priv->task); +} diff --git a/src/usb-acl-helper.h b/src/usb-acl-helper.h new file mode 100644 index 0000000..e2e27db --- /dev/null +++ b/src/usb-acl-helper.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_USB_ACL_HELPER_H__ +#define __SPICE_USB_ACL_HELPER_H__ + +#include "spice-client.h" +#include <gio/gio.h> + +/* Note the entire usb-acl-helper class is private to spice-client-glib !! */ + +G_BEGIN_DECLS + +#define SPICE_TYPE_USB_ACL_HELPER (spice_usb_acl_helper_get_type ()) +#define SPICE_USB_ACL_HELPER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_USB_ACL_HELPER, SpiceUsbAclHelper)) +#define SPICE_USB_ACL_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_USB_ACL_HELPER, SpiceUsbAclHelperClass)) +#define SPICE_IS_USB_ACL_HELPER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_USB_ACL_HELPER)) +#define SPICE_IS_USB_ACL_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_USB_ACL_HELPER)) +#define SPICE_USB_ACL_HELPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_USB_ACL_HELPER, SpiceUsbAclHelperClass)) + +typedef struct _SpiceUsbAclHelper SpiceUsbAclHelper; +typedef struct _SpiceUsbAclHelperClass SpiceUsbAclHelperClass; +typedef struct _SpiceUsbAclHelperPrivate SpiceUsbAclHelperPrivate; + +struct _SpiceUsbAclHelper +{ + GObject parent; + + /*< private >*/ + SpiceUsbAclHelperPrivate *priv; + /* Do not add fields to this struct */ +}; + +struct _SpiceUsbAclHelperClass +{ + GObjectClass parent_class; +}; + +GType spice_usb_acl_helper_get_type(void); + +SpiceUsbAclHelper *spice_usb_acl_helper_new(void); + +void spice_usb_acl_helper_open_acl_async(SpiceUsbAclHelper *self, + gint busnum, gint devnum, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean spice_usb_acl_helper_open_acl_finish( + SpiceUsbAclHelper *self, GAsyncResult *res, GError **err); + +void spice_usb_acl_helper_cancel(SpiceUsbAclHelper *self); + +G_END_DECLS + +#endif /* __SPICE_USB_ACL_HELPER_H__ */ diff --git a/src/usb-device-manager-priv.h b/src/usb-device-manager-priv.h new file mode 100644 index 0000000..b6fa9c9 --- /dev/null +++ b/src/usb-device-manager-priv.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011,2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_USB_DEVICE_MANAGER_PRIV_H__ +#define __SPICE_USB_DEVICE_MANAGER_PRIV_H__ + +#include "usb-device-manager.h" + +G_BEGIN_DECLS + +gboolean spice_usb_device_manager_start_event_listening( + SpiceUsbDeviceManager *manager, GError **err); + +void spice_usb_device_manager_stop_event_listening( + SpiceUsbDeviceManager *manager); + +#ifdef USE_USBREDIR +#include <libusb.h> +void spice_usb_device_manager_device_error( + SpiceUsbDeviceManager *manager, SpiceUsbDevice *device, GError *err); + +guint8 spice_usb_device_get_busnum(const SpiceUsbDevice *device); +guint8 spice_usb_device_get_devaddr(const SpiceUsbDevice *device); +guint16 spice_usb_device_get_vid(const SpiceUsbDevice *device); +guint16 spice_usb_device_get_pid(const SpiceUsbDevice *device); + +#endif + +G_END_DECLS + +#endif /* __SPICE_USB_DEVICE_MANAGER_PRIV_H__ */ diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c new file mode 100644 index 0000000..1fc8fc1 --- /dev/null +++ b/src/usb-device-manager.c @@ -0,0 +1,2266 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011, 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <glib-object.h> + +#ifdef USE_USBREDIR +#include <errno.h> +#include <libusb.h> + +#ifdef G_OS_WIN32 +#include "usbdk_api.h" +#endif + +#if defined(USE_GUDEV) +#include <gudev/gudev.h> +#elif defined(G_OS_WIN32) +#include "win-usb-dev.h" +#include "win-usb-driver-install.h" +#define USE_GUDEV /* win-usb-dev.h provides a fake gudev interface */ +#elif !defined USE_LIBUSB_HOTPLUG +#error "Expecting one of USE_GUDEV or USE_LIBUSB_HOTPLUG to be defined" +#endif + +#include "channel-usbredir-priv.h" +#include "usbredirhost.h" +#include "usbutil.h" +#endif + +#include "spice-session-priv.h" +#include "spice-client.h" +#include "spice-marshal.h" +#include "usb-device-manager-priv.h" + +#include <glib/gi18n.h> + +#ifndef G_OS_WIN32 /* Linux -- device id is bus.addr */ +#define DEV_ID_FMT "at %u.%u" +#else /* Windows -- device id is vid:pid */ +#define DEV_ID_FMT "0x%04x:0x%04x" +#endif + +/** + * SECTION:usb-device-manager + * @short_description: USB device management + * @title: Spice USB Manager + * @section_id: + * @see_also: + * @stability: Stable + * @include: spice-client.h + * + * #SpiceUsbDeviceManager monitors USB redirection channels and USB + * devices plugging/unplugging. If #SpiceUsbDeviceManager:auto-connect + * is set to %TRUE, it will automatically connect newly plugged USB + * devices to available channels. + * + * There should always be a 1:1 relation between #SpiceUsbDeviceManager objects + * and #SpiceSession objects. Therefor there is no + * spice_usb_device_manager_new, instead there is + * spice_usb_device_manager_get() which ensures this 1:1 relation. + */ + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_USB_DEVICE_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_USB_DEVICE_MANAGER, SpiceUsbDeviceManagerPrivate)) + +enum { + PROP_0, + PROP_SESSION, + PROP_AUTO_CONNECT, + PROP_AUTO_CONNECT_FILTER, + PROP_REDIRECT_ON_CONNECT, + PROP_FREE_CHANNELS, +}; + +enum +{ + DEVICE_ADDED, + DEVICE_REMOVED, + AUTO_CONNECT_FAILED, + DEVICE_ERROR, + LAST_SIGNAL, +}; + +struct _SpiceUsbDeviceManagerPrivate { + SpiceSession *session; + gboolean auto_connect; + gchar *auto_connect_filter; + gchar *redirect_on_connect; +#ifdef USE_USBREDIR + libusb_context *context; + int event_listeners; + GThread *event_thread; + gboolean event_thread_run; + struct usbredirfilter_rule *auto_conn_filter_rules; + struct usbredirfilter_rule *redirect_on_connect_rules; + int auto_conn_filter_rules_count; + int redirect_on_connect_rules_count; +#ifdef USE_GUDEV + GUdevClient *udev; + libusb_device **coldplug_list; /* Avoid needless reprobing during init */ +#else + gboolean redirecting; /* Handled by GUdevClient in the gudev case */ + libusb_hotplug_callback_handle hp_handle; +#endif +#ifdef G_OS_WIN32 + usbdk_api_wrapper *usbdk_api; + HANDLE usbdk_hider_handle; + SpiceWinUsbDriver *installer; +#endif + gboolean use_usbclerk; +#endif + GPtrArray *devices; + GPtrArray *channels; +}; + +enum { + SPICE_USB_DEVICE_STATE_NONE = 0, /* this is also DISCONNECTED */ + SPICE_USB_DEVICE_STATE_CONNECTING, + SPICE_USB_DEVICE_STATE_CONNECTED, + SPICE_USB_DEVICE_STATE_DISCONNECTING, + SPICE_USB_DEVICE_STATE_INSTALLING, + SPICE_USB_DEVICE_STATE_UNINSTALLING, + SPICE_USB_DEVICE_STATE_INSTALLED, + SPICE_USB_DEVICE_STATE_MAX +}; + +#ifdef USE_USBREDIR + +typedef struct _SpiceUsbDeviceInfo { + guint8 busnum; + guint8 devaddr; + guint16 vid; + guint16 pid; +#ifdef G_OS_WIN32 + guint8 state; +#else + libusb_device *libdev; +#endif + gint ref; +} SpiceUsbDeviceInfo; + + +static void channel_new(SpiceSession *session, SpiceChannel *channel, + gpointer user_data); +static void channel_destroy(SpiceSession *session, SpiceChannel *channel, + gpointer user_data); +#ifdef USE_GUDEV +static void spice_usb_device_manager_uevent_cb(GUdevClient *client, + const gchar *action, + GUdevDevice *udevice, + gpointer user_data); +static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self, + GUdevDevice *udev); +#else +static int spice_usb_device_manager_hotplug_cb(libusb_context *ctx, + libusb_device *device, + libusb_hotplug_event event, + void *data); +#endif +static void spice_usb_device_manager_check_redir_on_connect( + SpiceUsbDeviceManager *self, SpiceChannel *channel); + +static SpiceUsbDeviceInfo *spice_usb_device_new(libusb_device *libdev); +static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device); +static void spice_usb_device_unref(SpiceUsbDevice *device); + +#ifdef G_OS_WIN32 +static guint8 spice_usb_device_get_state(SpiceUsbDevice *device); +static void spice_usb_device_set_state(SpiceUsbDevice *device, guint8 s); + +static void _usbdk_hider_update(SpiceUsbDeviceManager *manager); +static void _usbdk_hider_clear(SpiceUsbDeviceManager *manager); +#endif + +static gboolean spice_usb_manager_device_equal_libdev(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, + libusb_device *libdev); +static libusb_device * +spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device); + +static void +_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +static +void _connect_device_async_cb(GObject *gobject, + GAsyncResult *channel_res, + gpointer user_data); + +G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, + (GBoxedCopyFunc)spice_usb_device_ref, + (GBoxedFreeFunc)spice_usb_device_unref) + +static void +_set_redirecting(SpiceUsbDeviceManager *self, gboolean is_redirecting) +{ +#ifdef USE_GUDEV + g_object_set(self->priv->udev, "redirecting", is_redirecting, NULL); +#else + self->priv->redirecting = is_redirecting; +#endif +} + +#else +G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref, g_object_unref) +#endif + +/** + * spice_usb_device_manager_is_redirecting: + * @self: the #SpiceUsbDeviceManager manager + * + * Checks whether a device is being redirected + * + * Returns: %TRUE if device redirection negotiation flow is in progress + * + * Since: 0.32 + */ +gboolean spice_usb_device_manager_is_redirecting(SpiceUsbDeviceManager *self) +{ +#ifdef USE_USBREDIR + +#ifdef USE_GUDEV + gboolean redirecting; + g_object_get(self->priv->udev, "redirecting", &redirecting, NULL); + return redirecting; +#else + return self->priv->redirecting; +#endif + +#else + return FALSE; +#endif +} + +static void spice_usb_device_manager_initable_iface_init(GInitableIface *iface); + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_CODE(SpiceUsbDeviceManager, spice_usb_device_manager, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, spice_usb_device_manager_initable_iface_init)); + +static void spice_usb_device_manager_init(SpiceUsbDeviceManager *self) +{ + SpiceUsbDeviceManagerPrivate *priv; + + priv = SPICE_USB_DEVICE_MANAGER_GET_PRIVATE(self); + self->priv = priv; + +#if defined(G_OS_WIN32) && defined(USE_USBREDIR) + priv->use_usbclerk = !usbdk_is_driver_installed() || + !(priv->usbdk_api = usbdk_api_load()); +#endif + priv->channels = g_ptr_array_new(); +#ifdef USE_USBREDIR + priv->devices = g_ptr_array_new_with_free_func((GDestroyNotify) + spice_usb_device_unref); +#endif +} + +static gboolean spice_usb_device_manager_initable_init(GInitable *initable, + GCancellable *cancellable, + GError **err) +{ +#ifdef USE_USBREDIR + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(initable); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + GList *list; + GList *it; + int rc; +#ifdef USE_GUDEV + const gchar *const subsystems[] = {"usb", NULL}; +#endif + +#ifdef G_OS_WIN32 + if (priv->use_usbclerk) { + priv->installer = spice_win_usb_driver_new(err); + if (!priv->installer) { + SPICE_DEBUG("failed to initialize winusb driver"); + return FALSE; + } + } +#endif + + /* Initialize libusb */ + rc = libusb_init(&priv->context); + if (rc < 0) { + const char *desc = spice_usbutil_libusb_strerror(rc); + g_warning("Error initializing USB support: %s [%i]", desc, rc); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error initializing USB support: %s [%i]", desc, rc); + return FALSE; + } + + /* Start listening for usb devices plug / unplug */ +#ifdef USE_GUDEV + priv->udev = g_udev_client_new(subsystems); + g_signal_connect(G_OBJECT(priv->udev), "uevent", + G_CALLBACK(spice_usb_device_manager_uevent_cb), self); + /* Do coldplug (detection of already connected devices) */ + libusb_get_device_list(priv->context, &priv->coldplug_list); + list = g_udev_client_query_by_subsystem(priv->udev, "usb"); + for (it = g_list_first(list); it; it = g_list_next(it)) { + spice_usb_device_manager_add_udev(self, it->data); + g_object_unref(it->data); + } + g_list_free(list); + libusb_free_device_list(priv->coldplug_list, 1); + priv->coldplug_list = NULL; +#else + rc = libusb_hotplug_register_callback(priv->context, + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, + LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, + spice_usb_device_manager_hotplug_cb, self, &priv->hp_handle); + if (rc < 0) { + const char *desc = spice_usbutil_libusb_strerror(rc); + g_warning("Error initializing USB hotplug support: %s [%i]", desc, rc); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Error initializing USB hotplug support: %s [%i]", desc, rc); + return FALSE; + } + spice_usb_device_manager_start_event_listening(self, NULL); +#endif + + /* Start listening for usb channels connect/disconnect */ + spice_g_signal_connect_object(priv->session, "channel-new", G_CALLBACK(channel_new), self, G_CONNECT_AFTER); + g_signal_connect(priv->session, "channel-destroy", + G_CALLBACK(channel_destroy), self); + list = spice_session_get_channels(priv->session); + for (it = g_list_first(list); it != NULL; it = g_list_next(it)) { + channel_new(priv->session, it->data, (gpointer*)self); + } + g_list_free(list); + + return TRUE; +#else + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection support not compiled in")); + return FALSE; +#endif +} + +static void spice_usb_device_manager_dispose(GObject *gobject) +{ +#ifdef USE_USBREDIR + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + +#ifdef USE_LIBUSB_HOTPLUG + if (priv->hp_handle) { + spice_usb_device_manager_stop_event_listening(self); + /* This also wakes up the libusb_handle_events() in the event_thread */ + libusb_hotplug_deregister_callback(priv->context, priv->hp_handle); + priv->hp_handle = 0; + } +#endif + if (priv->event_thread && !priv->event_thread_run) { + g_thread_join(priv->event_thread); + priv->event_thread = NULL; + } +#endif + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->dispose) + G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->dispose(gobject); +} + +static void spice_usb_device_manager_finalize(GObject *gobject) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + + g_ptr_array_unref(priv->channels); + if (priv->devices) + g_ptr_array_unref(priv->devices); + +#ifdef USE_USBREDIR +#ifdef USE_GUDEV + g_clear_object(&priv->udev); +#endif + g_return_if_fail(priv->event_thread == NULL); + if (priv->context) + libusb_exit(priv->context); + free(priv->auto_conn_filter_rules); + free(priv->redirect_on_connect_rules); +#ifdef G_OS_WIN32 + if (priv->installer) { + g_warn_if_fail(priv->use_usbclerk); + g_object_unref(priv->installer); + } + if (!priv->use_usbclerk) { + _usbdk_hider_clear(self); + usbdk_api_unload(priv->usbdk_api); + } +#endif +#endif + + g_free(priv->auto_connect_filter); + g_free(priv->redirect_on_connect); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->finalize) + G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->finalize(gobject); +} + +static void spice_usb_device_manager_initable_iface_init(GInitableIface *iface) +{ + iface->init = spice_usb_device_manager_initable_init; +} + +static void spice_usb_device_manager_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, priv->session); + break; + case PROP_AUTO_CONNECT: + g_value_set_boolean(value, priv->auto_connect); + break; + case PROP_AUTO_CONNECT_FILTER: + g_value_set_string(value, priv->auto_connect_filter); + break; + case PROP_REDIRECT_ON_CONNECT: + g_value_set_string(value, priv->redirect_on_connect); + break; + case PROP_FREE_CHANNELS: { + int free_channels = 0; +#ifdef USE_USBREDIR + int i; + for (i = 0; i < priv->channels->len; i++) { + SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i); + + if (!spice_usbredir_channel_get_device(channel)) + free_channels++; + } +#endif + g_value_set_int(value, free_channels); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_usb_device_manager_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + priv->session = g_value_get_object(value); + break; + case PROP_AUTO_CONNECT: + priv->auto_connect = g_value_get_boolean(value); +#if defined(G_OS_WIN32) && defined(USE_USBREDIR) + if (!priv->use_usbclerk) { + _usbdk_hider_update(self); + } +#endif + break; + case PROP_AUTO_CONNECT_FILTER: { + const gchar *filter = g_value_get_string(value); +#ifdef USE_USBREDIR + struct usbredirfilter_rule *rules; + int r, count; + + r = usbredirfilter_string_to_rules(filter, ",", "|", &rules, &count); + if (r) { + if (r == -ENOMEM) + g_error("Failed to allocate memory for auto-connect-filter"); + g_warning("Error parsing auto-connect-filter string, keeping old filter"); + break; + } + + SPICE_DEBUG("auto-connect filter set to %s", filter); + free(priv->auto_conn_filter_rules); + priv->auto_conn_filter_rules = rules; + priv->auto_conn_filter_rules_count = count; +#endif + g_free(priv->auto_connect_filter); + priv->auto_connect_filter = g_strdup(filter); + +#if defined(G_OS_WIN32) && defined(USE_USBREDIR) + if (!priv->use_usbclerk) { + _usbdk_hider_update(self); + } +#endif + break; + } + case PROP_REDIRECT_ON_CONNECT: { + const gchar *filter = g_value_get_string(value); +#ifdef USE_USBREDIR + struct usbredirfilter_rule *rules = NULL; + int r = 0, count = 0; + + if (filter) + r = usbredirfilter_string_to_rules(filter, ",", "|", + &rules, &count); + if (r) { + if (r == -ENOMEM) + g_error("Failed to allocate memory for redirect-on-connect"); + g_warning("Error parsing redirect-on-connect string, keeping old filter"); + break; + } + + SPICE_DEBUG("redirect-on-connect filter set to %s", filter); + free(priv->redirect_on_connect_rules); + priv->redirect_on_connect_rules = rules; + priv->redirect_on_connect_rules_count = count; +#endif + g_free(priv->redirect_on_connect); + priv->redirect_on_connect = g_strdup(filter); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->dispose = spice_usb_device_manager_dispose; + gobject_class->finalize = spice_usb_device_manager_finalize; + gobject_class->get_property = spice_usb_device_manager_get_property; + gobject_class->set_property = spice_usb_device_manager_set_property; + + /** + * SpiceUsbDeviceManager:session: + * + * #SpiceSession this #SpiceUsbDeviceManager is associated with + * + **/ + g_object_class_install_property + (gobject_class, PROP_SESSION, + g_param_spec_object("session", + "Session", + "SpiceSession", + SPICE_TYPE_SESSION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * SpiceUsbDeviceManager:auto-connect: + * + * Set this to TRUE to automatically redirect newly plugged in device. + * + * Note when #SpiceGtkSession's auto-usbredir property is TRUE, this + * property is controlled by #SpiceGtkSession. + */ + pspec = g_param_spec_boolean("auto-connect", "Auto Connect", + "Auto connect plugged in USB devices", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_AUTO_CONNECT, pspec); + + /** + * SpiceUsbDeviceManager:auto-connect-filter: + * + * Set a string specifying a filter to use to determine which USB devices + * to autoconnect when plugged in, a filter consists of one or more rules. + * Where each rule has the form of: + * + * @class,@vendor,@product,@version,@allow + * + * Use -1 for @class/@vendor/@product/@version to accept any value. + * + * And the rules themselves are concatenated like this: + * + * @rule1|@rule2|@rule3 + * + * The default setting filters out HID (class 0x03) USB devices from auto + * connect and auto connects anything else. Note the explicit allow rule at + * the end, this is necessary since by default all devices without a + * matching filter rule will not auto-connect. + * + * Filter strings in this format can be easily created with the RHEV-M + * USB filter editor tool. + */ + pspec = g_param_spec_string("auto-connect-filter", "Auto Connect Filter ", + "Filter determining which USB devices to auto connect", + "0x03,-1,-1,-1,0|-1,-1,-1,-1,1", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_AUTO_CONNECT_FILTER, + pspec); + + /** + * SpiceUsbDeviceManager:redirect-on-connect: + * + * Set a string specifying a filter selecting USB devices to automatically + * redirect after a Spice connection has been established. + * + * See #SpiceUsbDeviceManager:auto-connect-filter for the filter string + * format. + */ + pspec = g_param_spec_string("redirect-on-connect", "Redirect on connect", + "Filter selecting USB devices to redirect on connect", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_REDIRECT_ON_CONNECT, + pspec); + + /** + * SpiceUsbDeviceManager:n-free-channels: + * + * Get a list of avaialable channels for redirecting USB devices. + * + * Since: 0.31 + */ + pspec = g_param_spec_int("free-channels", "Free channels", + "The number of available channels for redirecting USB devices", + 0, + G_MAXINT, + 0, + G_PARAM_READABLE); + g_object_class_install_property(gobject_class, PROP_FREE_CHANNELS, + pspec); + + /** + * SpiceUsbDeviceManager::device-added: + * @manager: the #SpiceUsbDeviceManager that emitted the signal + * @device: #SpiceUsbDevice boxed object corresponding to the added device + * + * The #SpiceUsbDeviceManager::device-added signal is emitted whenever + * a new USB device has been plugged in. + **/ + signals[DEVICE_ADDED] = + g_signal_new("device-added", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceUsbDeviceManagerClass, device_added), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_USB_DEVICE); + + /** + * SpiceUsbDeviceManager::device-removed: + * @manager: the #SpiceUsbDeviceManager that emitted the signal + * @device: #SpiceUsbDevice boxed object corresponding to the removed device + * + * The #SpiceUsbDeviceManager::device-removed signal is emitted whenever + * an USB device has been removed. + **/ + signals[DEVICE_REMOVED] = + g_signal_new("device-removed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceUsbDeviceManagerClass, device_removed), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + SPICE_TYPE_USB_DEVICE); + + /** + * SpiceUsbDeviceManager::auto-connect-failed: + * @manager: the #SpiceUsbDeviceManager that emitted the signal + * @device: #SpiceUsbDevice boxed object corresponding to the device which failed to auto connect + * @error: #GError describing the reason why the autoconnect failed + * + * The #SpiceUsbDeviceManager::auto-connect-failed signal is emitted + * whenever the auto-connect property is true, and a newly plugged in + * device could not be auto-connected. + **/ + signals[AUTO_CONNECT_FAILED] = + g_signal_new("auto-connect-failed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceUsbDeviceManagerClass, auto_connect_failed), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, + 2, + SPICE_TYPE_USB_DEVICE, + G_TYPE_ERROR); + + /** + * SpiceUsbDeviceManager::device-error: + * @manager: #SpiceUsbDeviceManager that emitted the signal + * @device: #SpiceUsbDevice boxed object corresponding to the device which has an error + * @error: #GError describing the error + * + * The #SpiceUsbDeviceManager::device-error signal is emitted whenever an + * error happens which causes a device to no longer be available to the + * guest. + **/ + signals[DEVICE_ERROR] = + g_signal_new("device-error", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceUsbDeviceManagerClass, device_error), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, + 2, + SPICE_TYPE_USB_DEVICE, + G_TYPE_ERROR); + + g_type_class_add_private(klass, sizeof(SpiceUsbDeviceManagerPrivate)); +} + +#ifdef USE_USBREDIR + +/* ------------------------------------------------------------------ */ +/* gudev / libusb Helper functions */ + +#ifdef USE_GUDEV +static gboolean spice_usb_device_manager_get_udev_bus_n_address( + SpiceUsbDeviceManager *manager, GUdevDevice *udev, + int *bus, int *address) +{ + const gchar *bus_str, *address_str; + + *bus = *address = 0; + + if (manager->priv->use_usbclerk) { + /* Windows WinUsb/UsbClerk -- request vid:pid instead */ + bus_str = g_udev_device_get_property(udev, "VID"); + address_str = g_udev_device_get_property(udev, "PID"); + } else { + /* Linux or UsbDk backend on Windows*/ + bus_str = g_udev_device_get_property(udev, "BUSNUM"); + address_str = g_udev_device_get_property(udev, "DEVNUM"); + } + if (bus_str) + *bus = atoi(bus_str); + if (address_str) + *address = atoi(address_str); + + return *bus && *address; +} +#endif + +static gboolean spice_usb_device_manager_get_device_descriptor( + libusb_device *libdev, + struct libusb_device_descriptor *desc) +{ + int errcode; + const gchar *errstr; + + g_return_val_if_fail(libdev != NULL, FALSE); + g_return_val_if_fail(desc != NULL, FALSE); + + errcode = libusb_get_device_descriptor(libdev, desc); + if (errcode < 0) { + int bus, addr; + + bus = libusb_get_bus_number(libdev); + addr = libusb_get_device_address(libdev); + errstr = spice_usbutil_libusb_strerror(errcode); + g_warning("cannot get device descriptor for (%p) %d.%d -- %s(%d)", + libdev, bus, addr, errstr, errcode); + return FALSE; + } + return TRUE; +} + + +/** + * spice_usb_device_get_libusb_device: + * @device: #SpiceUsbDevice to get the descriptor information of + * + * Finds the %libusb_device associated with the @device. + * + * Returns: (transfer none): the %libusb_device associated to %SpiceUsbDevice. + * + * Since: 0.27 + **/ +gconstpointer +spice_usb_device_get_libusb_device(const SpiceUsbDevice *device G_GNUC_UNUSED) +{ +#ifdef USE_USBREDIR +#ifndef G_OS_WIN32 + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, FALSE); + + return info->libdev; +#endif +#endif + return NULL; +} + +static gboolean spice_usb_device_manager_get_libdev_vid_pid( + libusb_device *libdev, int *vid, int *pid) +{ + struct libusb_device_descriptor desc; + + g_return_val_if_fail(libdev != NULL, FALSE); + g_return_val_if_fail(vid != NULL, FALSE); + g_return_val_if_fail(pid != NULL, FALSE); + + *vid = *pid = 0; + + if (!spice_usb_device_manager_get_device_descriptor(libdev, &desc)) { + return FALSE; + } + *vid = desc.idVendor; + *pid = desc.idProduct; + + return TRUE; +} + +/* ------------------------------------------------------------------ */ +/* callbacks */ + +static void channel_new(SpiceSession *session, SpiceChannel *channel, + gpointer user_data) +{ + SpiceUsbDeviceManager *self = user_data; + + if (!SPICE_IS_USBREDIR_CHANNEL(channel)) + return; + + spice_usbredir_channel_set_context(SPICE_USBREDIR_CHANNEL(channel), + self->priv->context); + spice_channel_connect(channel); + g_ptr_array_add(self->priv->channels, channel); + + spice_usb_device_manager_check_redir_on_connect(self, channel); + + /* + * add a reference to ourself, to make sure the libusb context is + * alive as long as the channel is. + * TODO: moving to gusb could help here too. + */ + g_object_ref(self); + g_object_weak_ref(G_OBJECT(channel), (GWeakNotify)g_object_unref, self); +} + +static void channel_destroy(SpiceSession *session, SpiceChannel *channel, + gpointer user_data) +{ + SpiceUsbDeviceManager *self = user_data; + + if (!SPICE_IS_USBREDIR_CHANNEL(channel)) + return; + + g_ptr_array_remove(self->priv->channels, channel); +} + +static void spice_usb_device_manager_auto_connect_cb(GObject *gobject, + GAsyncResult *res, + gpointer user_data) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + SpiceUsbDevice *device = user_data; + GError *err = NULL; + + spice_usb_device_manager_connect_device_finish(self, res, &err); + if (err) { + gchar *desc = spice_usb_device_get_description(device, NULL); + g_prefix_error(&err, "Could not auto-redirect %s: ", desc); + g_free(desc); + + SPICE_DEBUG("%s", err->message); + g_signal_emit(self, signals[AUTO_CONNECT_FAILED], 0, device, err); + g_error_free(err); + } + spice_usb_device_unref(device); +} + +static gboolean +spice_usb_device_manager_device_match(SpiceUsbDeviceManager *self, SpiceUsbDevice *device, + const int bus, const int address) +{ + if (self->priv->use_usbclerk) { + return (spice_usb_device_get_vid(device) == bus && + spice_usb_device_get_pid(device) == address); + } else { + return (spice_usb_device_get_busnum(device) == bus && + spice_usb_device_get_devaddr(device) == address); + } +} + +#ifdef USE_GUDEV +static gboolean +spice_usb_device_manager_libdev_match(SpiceUsbDeviceManager *self, libusb_device *libdev, + const int bus, const int address) +{ + if (self->priv->use_usbclerk) { + /* WinUSB -- match functions for Windows -- match by vid:pid */ + int vid, pid; + + if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid, &pid)) { + return FALSE; + } + return (bus == vid && address == pid); + } else { + /* match functions for Linux/UsbDk -- match by bus.addr */ + return (libusb_get_bus_number(libdev) == bus && + libusb_get_device_address(libdev) == address); + } +} +#endif + +static SpiceUsbDevice* +spice_usb_device_manager_find_device(SpiceUsbDeviceManager *self, + const int bus, const int address) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + SpiceUsbDevice *curr, *device = NULL; + guint i; + + for (i = 0; i < priv->devices->len; i++) { + curr = g_ptr_array_index(priv->devices, i); + if (spice_usb_device_manager_device_match(self, curr, bus, address)) { + device = curr; + break; + } + } + return device; +} + +static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager *self, + libusb_device *libdev) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + struct libusb_device_descriptor desc; + SpiceUsbDevice *device; + + if (!spice_usb_device_manager_get_device_descriptor(libdev, &desc)) + return; + + /* Skip hubs */ + if (desc.bDeviceClass == LIBUSB_CLASS_HUB) + return; + + device = (SpiceUsbDevice*)spice_usb_device_new(libdev); + if (!device) + return; + + g_ptr_array_add(priv->devices, device); + + if (priv->auto_connect) { + gboolean can_redirect, auto_ok; + + can_redirect = spice_usb_device_manager_can_redirect_device( + self, device, NULL); + + auto_ok = usbredirhost_check_device_filter( + priv->auto_conn_filter_rules, + priv->auto_conn_filter_rules_count, + libdev, 0) == 0; + + if (can_redirect && auto_ok) + spice_usb_device_manager_connect_device_async(self, + device, NULL, + spice_usb_device_manager_auto_connect_cb, + spice_usb_device_ref(device)); + } + + SPICE_DEBUG("device added %04x:%04x (%p)", + spice_usb_device_get_vid(device), + spice_usb_device_get_pid(device), + device); + g_signal_emit(self, signals[DEVICE_ADDED], 0, device); +} + +static void spice_usb_device_manager_remove_dev(SpiceUsbDeviceManager *self, + guint bus, guint address) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + SpiceUsbDevice *device; + + device = spice_usb_device_manager_find_device(self, bus, address); + if (!device) { + g_warning("Could not find USB device to remove " DEV_ID_FMT, + bus, address); + return; + } + +#ifdef G_OS_WIN32 + if (priv->use_usbclerk) { + const guint8 state = spice_usb_device_get_state(device); + if ((state == SPICE_USB_DEVICE_STATE_INSTALLING) || + (state == SPICE_USB_DEVICE_STATE_UNINSTALLING)) { + SPICE_DEBUG("skipping " DEV_ID_FMT ". It is un/installing its driver", + bus, address); + return; + } + } +#endif + + spice_usb_device_manager_disconnect_device(self, device); + + SPICE_DEBUG("device removed %04x:%04x (%p)", + spice_usb_device_get_vid(device), + spice_usb_device_get_pid(device), + device); + spice_usb_device_ref(device); + g_ptr_array_remove(priv->devices, device); + g_signal_emit(self, signals[DEVICE_REMOVED], 0, device); + spice_usb_device_unref(device); +} + +#ifdef USE_GUDEV +static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self, + GUdevDevice *udev) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + libusb_device *libdev = NULL, **dev_list = NULL; + SpiceUsbDevice *device; + const gchar *devtype; + int i, bus, address; + + devtype = g_udev_device_get_property(udev, "DEVTYPE"); + /* Check if this is a usb device (and not an interface) */ + if (!devtype || strcmp(devtype, "usb_device")) + return; + + if (!spice_usb_device_manager_get_udev_bus_n_address(self, udev, &bus, &address)) { + g_warning("USB device without bus number or device address"); + return; + } + + device = spice_usb_device_manager_find_device(self, bus, address); + if (device) { + SPICE_DEBUG("USB device 0x%04x:0x%04x at %d.%d already exists, ignored", + spice_usb_device_get_vid(device), + spice_usb_device_get_pid(device), + spice_usb_device_get_busnum(device), + spice_usb_device_get_devaddr(device)); + return; + } + + if (priv->coldplug_list) + dev_list = priv->coldplug_list; + else + libusb_get_device_list(priv->context, &dev_list); + + for (i = 0; dev_list && dev_list[i]; i++) { + if (spice_usb_device_manager_libdev_match(self, dev_list[i], bus, address)) { + libdev = dev_list[i]; + break; + } + } + + if (libdev) + spice_usb_device_manager_add_dev(self, libdev); + else + g_warning("Could not find USB device to add " DEV_ID_FMT, + (guint) bus, (guint) address); + + if (!priv->coldplug_list) + libusb_free_device_list(dev_list, 1); +} + +static void spice_usb_device_manager_remove_udev(SpiceUsbDeviceManager *self, + GUdevDevice *udev) +{ + int bus, address; + + if (!spice_usb_device_manager_get_udev_bus_n_address(self, udev, &bus, &address)) + return; + + spice_usb_device_manager_remove_dev(self, bus, address); +} + +static void spice_usb_device_manager_uevent_cb(GUdevClient *client, + const gchar *action, + GUdevDevice *udevice, + gpointer user_data) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data); + + if (g_str_equal(action, "add")) + spice_usb_device_manager_add_udev(self, udevice); + else if (g_str_equal (action, "remove")) + spice_usb_device_manager_remove_udev(self, udevice); +} +#else +struct hotplug_idle_cb_args { + SpiceUsbDeviceManager *self; + libusb_device *device; + libusb_hotplug_event event; +}; + +static gboolean spice_usb_device_manager_hotplug_idle_cb(gpointer user_data) +{ + struct hotplug_idle_cb_args *args = user_data; + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(args->self); + + switch (args->event) { + case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: + spice_usb_device_manager_add_dev(self, args->device); + break; + case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: + spice_usb_device_manager_remove_dev(self, + libusb_get_bus_number(args->device), + libusb_get_device_address(args->device)); + break; + } + libusb_unref_device(args->device); + g_object_unref(self); + g_free(args); + return FALSE; +} + +/* Can be called from both the main-thread as well as the event_thread */ +static int spice_usb_device_manager_hotplug_cb(libusb_context *ctx, + libusb_device *device, + libusb_hotplug_event event, + void *user_data) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data); + struct hotplug_idle_cb_args *args = g_malloc0(sizeof(*args)); + + args->self = g_object_ref(self); + args->device = libusb_ref_device(device); + args->event = event; + g_idle_add(spice_usb_device_manager_hotplug_idle_cb, args); + return 0; +} +#endif + +static void spice_usb_device_manager_channel_connect_cb( + GObject *gobject, GAsyncResult *channel_res, gpointer user_data) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject); + GTask *task = G_TASK(user_data); + GError *err = NULL; + + spice_usbredir_channel_connect_device_finish(channel, channel_res, &err); + if (err) + g_task_return_error(task, err); + else + g_task_return_boolean(task, TRUE); + + g_object_unref(task); +} + +#ifdef G_OS_WIN32 + +typedef struct _UsbInstallCbInfo { + SpiceUsbDeviceManager *manager; + SpiceUsbDevice *device; + SpiceWinUsbDriver *installer; + GCancellable *cancellable; + GAsyncReadyCallback callback; + gpointer user_data; +} UsbInstallCbInfo; + +/** + * spice_usb_device_manager_drv_install_cb: + * @gobject: #SpiceWinUsbDriver in charge of installing the driver + * @res: #GAsyncResult of async win usb driver installation + * @user_data: #SpiceUsbDeviceManager requested the installation + * + * Called when an Windows libusb driver installation completed. + * + * If the driver installation was successful, continue with USB + * device redirection + * + * Always call _spice_usb_device_manager_connect_device_async. + * When installation fails, libusb_open fails too, but cleanup would be better. + */ +static void spice_usb_device_manager_drv_install_cb(GObject *gobject, + GAsyncResult *res, + gpointer user_data) +{ + SpiceUsbDeviceManager *self; + SpiceWinUsbDriver *installer; + GError *err = NULL; + SpiceUsbDevice *device; + UsbInstallCbInfo *cbinfo; + GCancellable *cancellable; + gpointer data; + + g_return_if_fail(user_data != NULL); + + cbinfo = user_data; + self = cbinfo->manager; + device = cbinfo->device; + installer = cbinfo->installer; + cancellable = cbinfo->cancellable; + data = cbinfo->user_data; + + g_free(cbinfo); + + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + g_return_if_fail(self->priv->use_usbclerk); + g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(installer)); + g_return_if_fail(device!= NULL); + + SPICE_DEBUG("Win USB driver install finished"); + + if (!spice_win_usb_driver_install_finish(installer, res, &err)) { + g_warning("win usb driver install failed -- %s", err->message); + g_error_free(err); + } + + spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLED); + + /* device is already ref'ed */ + _spice_usb_device_manager_connect_device_async(self, + device, + cancellable, + _connect_device_async_cb, + data); + + spice_usb_device_unref(device); +} + +static void spice_usb_device_manager_drv_uninstall_cb(GObject *gobject, + GAsyncResult *res, + gpointer user_data) +{ + GError *err = NULL; + + UsbInstallCbInfo *cbinfo = user_data; + SpiceUsbDeviceManager *self = cbinfo->manager; + SpiceUsbDevice *device = cbinfo->device; + SpiceWinUsbDriver *installer = cbinfo->installer; + + g_free(cbinfo); + + SPICE_DEBUG("Win USB driver uninstall finished"); + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + g_return_if_fail(self->priv->use_usbclerk); + + if (!spice_win_usb_driver_uninstall_finish(installer, res, &err)) { + g_warning("win usb driver uninstall failed -- %s", err->message); + g_clear_error(&err); + } + + spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_NONE); + spice_usb_device_unref(device); +} + +#endif + +/* ------------------------------------------------------------------ */ +/* private api */ + +static gpointer spice_usb_device_manager_usb_ev_thread(gpointer user_data) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(user_data); + SpiceUsbDeviceManagerPrivate *priv = self->priv; + int rc; + + while (priv->event_thread_run) { + rc = libusb_handle_events(priv->context); + if (rc && rc != LIBUSB_ERROR_INTERRUPTED) { + const char *desc = spice_usbutil_libusb_strerror(rc); + g_warning("Error handling USB events: %s [%i]", desc, rc); + break; + } + } + + return NULL; +} + +gboolean spice_usb_device_manager_start_event_listening( + SpiceUsbDeviceManager *self, GError **err) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + + g_return_val_if_fail(err == NULL || *err == NULL, FALSE); + + priv->event_listeners++; + if (priv->event_listeners > 1) + return TRUE; + + /* We don't join the thread when we stop event listening, as the + libusb_handle_events call in the thread won't exit until the + libusb_close call for the device is made from usbredirhost_close. */ + if (priv->event_thread) { + g_thread_join(priv->event_thread); + priv->event_thread = NULL; + } + priv->event_thread_run = TRUE; + priv->event_thread = g_thread_new("usb_ev_thread", + spice_usb_device_manager_usb_ev_thread, + self); + return priv->event_thread != NULL; +} + +void spice_usb_device_manager_stop_event_listening( + SpiceUsbDeviceManager *self) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + + g_return_if_fail(priv->event_listeners > 0); + + priv->event_listeners--; + if (priv->event_listeners == 0) + priv->event_thread_run = FALSE; +} + +static void spice_usb_device_manager_check_redir_on_connect( + SpiceUsbDeviceManager *self, SpiceChannel *channel) +{ + SpiceUsbDeviceManagerPrivate *priv = self->priv; + GTask *task; + SpiceUsbDevice *device; + libusb_device *libdev; + guint i; + + if (priv->redirect_on_connect == NULL) + return; + + for (i = 0; i < priv->devices->len; i++) { + device = g_ptr_array_index(priv->devices, i); + + if (spice_usb_device_manager_is_device_connected(self, device)) + continue; + + libdev = spice_usb_device_manager_device_to_libdev(self, device); +#ifdef G_OS_WIN32 + if (libdev == NULL) + continue; +#endif + if (usbredirhost_check_device_filter( + priv->redirect_on_connect_rules, + priv->redirect_on_connect_rules_count, + libdev, 0) == 0) { + /* Note: re-uses spice_usb_device_manager_connect_device_async's + completion handling code! */ + task = g_task_new(self, + NULL, + spice_usb_device_manager_auto_connect_cb, + spice_usb_device_ref(device)); + + spice_usbredir_channel_connect_device_async( + SPICE_USBREDIR_CHANNEL(channel), + libdev, device, NULL, + spice_usb_device_manager_channel_connect_cb, + task); + libusb_unref_device(libdev); + return; /* We've taken the channel! */ + } + + libusb_unref_device(libdev); + } +} + +void spice_usb_device_manager_device_error( + SpiceUsbDeviceManager *self, SpiceUsbDevice *device, GError *err) +{ + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + g_return_if_fail(device != NULL); + + g_signal_emit(self, signals[DEVICE_ERROR], 0, device, err); +} +#endif + +static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev( + SpiceUsbDeviceManager *manager, SpiceUsbDevice *device) +{ +#ifdef USE_USBREDIR + SpiceUsbDeviceManagerPrivate *priv = manager->priv; + guint i; + + for (i = 0; i < priv->channels->len; i++) { + SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i); + spice_usbredir_channel_lock(channel); + libusb_device *libdev = spice_usbredir_channel_get_device(channel); + if (spice_usb_manager_device_equal_libdev(manager, device, libdev)) { + spice_usbredir_channel_unlock(channel); + return channel; + } + spice_usbredir_channel_unlock(channel); + } +#endif + return NULL; +} + +/* ------------------------------------------------------------------ */ +/* public api */ + +/** + * spice_usb_device_manager_get_devices_with_filter: + * @manager: the #SpiceUsbDeviceManager manager + * @filter: (allow-none): filter string for selecting which devices to return, + * see #SpiceUsbDeviceManager:auto-connect-filter for the filter + * string format + * + * Finds devices associated with the @manager complying with the @filter + * + * Returns: (element-type SpiceUsbDevice) (transfer full): a + * %GPtrArray array of %SpiceUsbDevice + * + * Since: 0.20 + */ +GPtrArray* spice_usb_device_manager_get_devices_with_filter( + SpiceUsbDeviceManager *self, const gchar *filter) +{ + GPtrArray *devices_copy = NULL; + + g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), NULL); + +#ifdef USE_USBREDIR + SpiceUsbDeviceManagerPrivate *priv = self->priv; + struct usbredirfilter_rule *rules = NULL;; + int r, count = 0; + guint i; + + if (filter) { + r = usbredirfilter_string_to_rules(filter, ",", "|", &rules, &count); + if (r) { + if (r == -ENOMEM) + g_error("Failed to allocate memory for filter"); + g_warning("Error parsing filter, ignoring"); + rules = NULL; + count = 0; + } + } + + devices_copy = g_ptr_array_new_with_free_func((GDestroyNotify) + spice_usb_device_unref); + for (i = 0; i < priv->devices->len; i++) { + SpiceUsbDevice *device = g_ptr_array_index(priv->devices, i); + + if (rules) { + libusb_device *libdev = + spice_usb_device_manager_device_to_libdev(self, device); +#ifdef G_OS_WIN32 + if (libdev == NULL) + continue; +#endif + if (usbredirhost_check_device_filter(rules, count, libdev, 0) != 0) + continue; + } + g_ptr_array_add(devices_copy, spice_usb_device_ref(device)); + } + + free(rules); +#endif + + return devices_copy; +} + +/** + * spice_usb_device_manager_get_devices: + * @manager: the #SpiceUsbDeviceManager manager + * + * Finds devices associated with the @manager + * + * Returns: (element-type SpiceUsbDevice) (transfer full): a %GPtrArray array of %SpiceUsbDevice + */ +GPtrArray* spice_usb_device_manager_get_devices(SpiceUsbDeviceManager *self) +{ + return spice_usb_device_manager_get_devices_with_filter(self, NULL); +} + +/** + * spice_usb_device_manager_is_device_connected: + * @manager: the #SpiceUsbDeviceManager manager + * @device: a #SpiceUsbDevice + * + * Finds if the @device is connected. + * + * Returns: %TRUE if @device has an associated USB redirection channel + */ +gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device) +{ + g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), FALSE); + g_return_val_if_fail(device != NULL, FALSE); + + return !!spice_usb_device_manager_get_channel_for_dev(self, device); +} + +#if defined(USE_USBREDIR) && defined(G_OS_WIN32) + +static void +_spice_usb_device_manager_install_driver_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceWinUsbDriver *installer; + UsbInstallCbInfo *cbinfo; + + g_return_if_fail(self->priv->installer); + + spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLING); + + installer = self->priv->installer; + cbinfo = g_new0(UsbInstallCbInfo, 1); + cbinfo->manager = self; + cbinfo->device = spice_usb_device_ref(device); + cbinfo->installer = installer; + cbinfo->cancellable = cancellable; + cbinfo->callback = callback; + cbinfo->user_data = user_data; + + spice_win_usb_driver_install_async(installer, device, cancellable, + spice_usb_device_manager_drv_install_cb, + cbinfo); +} + +static void +_spice_usb_device_manager_uninstall_driver_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device) +{ + SpiceWinUsbDriver *installer; + UsbInstallCbInfo *cbinfo; + guint8 state; + + g_warn_if_fail(device != NULL); + g_return_if_fail(self->priv->installer); + + state = spice_usb_device_get_state(device); + if ((state != SPICE_USB_DEVICE_STATE_INSTALLED) && + (state != SPICE_USB_DEVICE_STATE_CONNECTED)) { + return; + } + + spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_UNINSTALLING); + + installer = self->priv->installer; + cbinfo = g_new0(UsbInstallCbInfo, 1); + cbinfo->manager = self; + cbinfo->device = spice_usb_device_ref(device); + cbinfo->installer = installer; + + spice_win_usb_driver_uninstall_async(installer, device, NULL, + spice_usb_device_manager_drv_uninstall_cb, + cbinfo); +} + +#endif + +#ifdef USE_USBREDIR + +static gboolean +_spice_usb_device_manager_connect_device_finish(SpiceUsbDeviceManager *self, + GAsyncResult *res, + GError **error) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, G_OBJECT(self)), FALSE); + + return g_task_propagate_boolean(task, error); +} + +static void +_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + g_return_if_fail(device != NULL); + + SPICE_DEBUG("connecting device %p", device); + + task = g_task_new(self, cancellable, callback, user_data); + + SpiceUsbDeviceManagerPrivate *priv = self->priv; + libusb_device *libdev; + guint i; + + if (spice_usb_device_manager_is_device_connected(self, device)) { + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + "Cannot connect an already connected usb device"); + goto done; + } + + for (i = 0; i < priv->channels->len; i++) { + SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i); + + if (spice_usbredir_channel_get_device(channel)) + continue; /* Skip already used channels */ + + libdev = spice_usb_device_manager_device_to_libdev(self, device); +#ifdef G_OS_WIN32 + if (libdev == NULL) { + /* Most likely, the device was plugged out at driver installation + * time, and its remove-device event was ignored. + * So remove the device now + */ + SPICE_DEBUG("libdev does not exist for %p -- removing", device); + spice_usb_device_ref(device); + g_ptr_array_remove(priv->devices, device); + g_signal_emit(self, signals[DEVICE_REMOVED], 0, device); + spice_usb_device_unref(device); + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_FAILED, + _("Device was not found")); + goto done; + } +#endif + spice_usbredir_channel_connect_device_async(channel, + libdev, + device, + cancellable, + spice_usb_device_manager_channel_connect_cb, + task); + libusb_unref_device(libdev); + return; + } + + g_task_return_new_error(task, + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("No free USB channel")); +done: + g_object_unref(task); +} + +#endif + +/** + * spice_usb_device_manager_connect_device_async: + * @self: a #SpiceUsbDeviceManager. + * @device: a #SpiceUsbDevice to redirect + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: the data to pass to callback function + * + * Asynchronously connects the @device. When completed, @callback will be called. + * Then it is possible to call spice_usb_device_manager_connect_device_finish() + * to get the result of the operation. + */ +void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + +#ifdef USE_USBREDIR + + GTask *task = + g_task_new(G_OBJECT(self), cancellable, callback, user_data); + + _set_redirecting(self, TRUE); + +#ifdef G_OS_WIN32 + if (self->priv->use_usbclerk) { + _spice_usb_device_manager_install_driver_async(self, device, cancellable, + callback, task); + return; + } +#endif + + _spice_usb_device_manager_connect_device_async(self, + device, + cancellable, + _connect_device_async_cb, + task); + +#endif +} + +/** + * spice_usb_device_manager_connect_device_finish: + * @self: a #SpiceUsbDeviceManager. + * @res: a #GAsyncResult + * @err: (allow-none): a return location for a #GError, or %NULL. + * + * Finishes an async operation. See spice_usb_device_manager_connect_device_async(). + * + * Returns: %TRUE if connection is successful + */ +gboolean spice_usb_device_manager_connect_device_finish( + SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, self), + FALSE); + + return g_task_propagate_boolean(task, err); +} + +/** + * spice_usb_device_manager_disconnect_device_finish: + * @self: a #SpiceUsbDeviceManager. + * @res: a #GAsyncResult + * @err: (allow-none): a return location for a #GError, or %NULL. + * + * Finishes an async operation. See spice_usb_device_manager_disconnect_device_async(). + * + * Returns: %TRUE if disconnection is successful + */ +gboolean spice_usb_device_manager_disconnect_device_finish( + SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(task, G_OBJECT(self)), FALSE); + + return g_task_propagate_boolean(task, err); +} + +#ifdef USE_USBREDIR +static +void _connect_device_async_cb(GObject *gobject, + GAsyncResult *channel_res, + gpointer user_data) +{ + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject); + GTask *task = user_data; + GError *error = NULL; + + _set_redirecting(self, FALSE); + if (_spice_usb_device_manager_connect_device_finish(self, channel_res, &error)) + g_task_return_boolean(task, TRUE); + else + g_task_return_error(task, error); + g_object_unref(task); +} +#endif + +/** + * spice_usb_device_manager_disconnect_device: + * @manager: the #SpiceUsbDeviceManager manager + * @device: a #SpiceUsbDevice to disconnect + * + * Disconnects the @device. + */ +void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device) +{ + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + g_return_if_fail(device != NULL); + + SPICE_DEBUG("disconnecting device %p", device); + +#ifdef USE_USBREDIR + SpiceUsbredirChannel *channel; + + channel = spice_usb_device_manager_get_channel_for_dev(self, device); + if (channel) + spice_usbredir_channel_disconnect_device(channel); + +#ifdef G_OS_WIN32 + if(self->priv->use_usbclerk) + _spice_usb_device_manager_uninstall_driver_async(self, device); +#endif + +#endif +} + +typedef struct _disconnect_cb_data +{ + SpiceUsbDeviceManager *self; + SpiceUsbDevice *device; +} disconnect_cb_data; + +#ifdef USE_USBREDIR +static +void _disconnect_device_async_cb(GObject *gobject, + GAsyncResult *channel_res, + gpointer user_data) +{ + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject); + GTask *task = user_data; + GError *err = NULL; + disconnect_cb_data *data = g_task_get_task_data(task); + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(data->self); + +#ifdef G_OS_WIN32 + if (self->priv->use_usbclerk) { + _spice_usb_device_manager_uninstall_driver_async(self, data->device); + } +#endif + + _set_redirecting(self, FALSE); + + spice_usbredir_channel_disconnect_device_finish(channel, channel_res, &err); + if (err) + g_task_return_error(task, err); + else + g_task_return_boolean(task, TRUE); + + g_object_unref(task); +} +#endif + +void spice_usb_device_manager_disconnect_device_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ +#ifdef USE_USBREDIR + GTask *nested; + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + + g_return_if_fail(device != NULL); + g_return_if_fail(spice_usb_device_manager_is_device_connected(self, device)); + + SPICE_DEBUG("disconnecting device %p", device); + + SpiceUsbredirChannel *channel; + + _set_redirecting(self, TRUE); + + channel = spice_usb_device_manager_get_channel_for_dev(self, device); + nested = g_task_new(G_OBJECT(self), cancellable, callback, user_data); + disconnect_cb_data *data = g_new(disconnect_cb_data, 1); + data->self = self; + data->device = device; + g_task_set_task_data(nested, data, g_free); + + spice_usbredir_channel_disconnect_device_async(channel, cancellable, + _disconnect_device_async_cb, + nested); +#endif +} + +/** + * spice_usb_device_manager_can_redirect_device: + * @self: the #SpiceUsbDeviceManager manager + * @device: a #SpiceUsbDevice to disconnect + * @err: (allow-none): a return location for a #GError, or %NULL. + * + * Checks whether it is possible to redirect the @device. + * + * Returns: %TRUE if @device can be redirected + */ +gboolean +spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GError **err) +{ +#ifdef USE_USBREDIR + const struct usbredirfilter_rule *guest_filter_rules = NULL; + SpiceUsbDeviceManagerPrivate *priv = self->priv; + int i, guest_filter_rules_count; + + g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), FALSE); + g_return_val_if_fail(device != NULL, FALSE); + g_return_val_if_fail(err == NULL || *err == NULL, FALSE); + + if (!spice_session_get_usbredir_enabled(priv->session)) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection is disabled")); + return FALSE; + } + + if (!priv->channels->len) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("The connected VM is not configured for USB redirection")); + return FALSE; + } + + /* Skip the other checks for already connected devices */ + if (spice_usb_device_manager_is_device_connected(self, device)) + return TRUE; + + /* We assume all channels have the same filter, so we just take the + filter from the first channel */ + spice_usbredir_channel_get_guest_filter( + g_ptr_array_index(priv->channels, 0), + &guest_filter_rules, &guest_filter_rules_count); + + if (guest_filter_rules) { + gboolean filter_ok; + libusb_device *libdev; + + libdev = spice_usb_device_manager_device_to_libdev(self, device); +#ifdef G_OS_WIN32 + if (libdev == NULL) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("Some USB devices were not found")); + return FALSE; + } +#endif + filter_ok = (usbredirhost_check_device_filter( + guest_filter_rules, guest_filter_rules_count, + libdev, 0) == 0); + libusb_unref_device(libdev); + if (!filter_ok) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("Some USB devices are blocked by host policy")); + return FALSE; + } + } + + /* Check if there are free channels */ + for (i = 0; i < priv->channels->len; i++) { + SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i); + spice_usbredir_channel_lock(channel); + + if (!spice_usbredir_channel_get_device(channel)){ + spice_usbredir_channel_unlock(channel); + break; + } + spice_usbredir_channel_unlock(channel); + } + if (i == priv->channels->len) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("There are no free USB channels")); + return FALSE; + } + + return TRUE; +#else + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection support not compiled in")); + return FALSE; +#endif +} + +/** + * spice_usb_device_get_description: + * @device: #SpiceUsbDevice to get the description of + * @format: (allow-none): an optional printf() format string with + * positional parameters + * + * Get a string describing the device which is suitable as a description of + * the device for the end user. The returned string should be freed with + * g_free() when no longer needed. + * + * The @format positional parameters are the following: + * - '%%1$s' manufacturer + * - '%%2$s' product + * - '%%3$s' descriptor (a [vendor_id:product_id] string) + * - '%%4$d' bus + * - '%%5$d' address + * + * (the default format string is "%%s %%s %%s at %%d-%%d") + * + * Returns: a newly-allocated string holding the description, or %NULL if failed + */ +gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *format) +{ +#ifdef USE_USBREDIR + guint16 bus, address, vid, pid; + gchar *description, *descriptor, *manufacturer = NULL, *product = NULL; + + g_return_val_if_fail(device != NULL, NULL); + + bus = spice_usb_device_get_busnum(device); + address = spice_usb_device_get_devaddr(device); + vid = spice_usb_device_get_vid(device); + pid = spice_usb_device_get_pid(device); + + if ((vid > 0) && (pid > 0)) { + descriptor = g_strdup_printf("[%04x:%04x]", vid, pid); + } else { + descriptor = g_strdup(""); + } + + spice_usb_util_get_device_strings(bus, address, vid, pid, + &manufacturer, &product); + + if (!format) + format = _("%s %s %s at %d-%d"); + + description = g_strdup_printf(format, manufacturer, product, descriptor, bus, address); + + g_free(manufacturer); + g_free(descriptor); + g_free(product); + + return description; +#else + return NULL; +#endif +} + + + +#ifdef USE_USBREDIR +/* + * SpiceUsbDeviceInfo + */ +static SpiceUsbDeviceInfo *spice_usb_device_new(libusb_device *libdev) +{ + SpiceUsbDeviceInfo *info; + int vid, pid; + guint8 bus, addr; + + g_return_val_if_fail(libdev != NULL, NULL); + + bus = libusb_get_bus_number(libdev); + addr = libusb_get_device_address(libdev); + + if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid, &pid)) { + return NULL; + } + + info = g_new0(SpiceUsbDeviceInfo, 1); + + info->busnum = bus; + info->devaddr = addr; + info->vid = vid; + info->pid = pid; + info->ref = 1; +#ifndef G_OS_WIN32 + info->libdev = libusb_ref_device(libdev); +#endif + + return info; +} + +guint8 spice_usb_device_get_busnum(const SpiceUsbDevice *device) +{ + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->busnum; +} + +guint8 spice_usb_device_get_devaddr(const SpiceUsbDevice *device) +{ + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->devaddr; +} + +guint16 spice_usb_device_get_vid(const SpiceUsbDevice *device) +{ + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->vid; +} + +guint16 spice_usb_device_get_pid(const SpiceUsbDevice *device) +{ + const SpiceUsbDeviceInfo *info = (const SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->pid; +} + +#ifdef G_OS_WIN32 +void spice_usb_device_set_state(SpiceUsbDevice *device, guint8 state) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_if_fail(info != NULL); + + info->state = state; +} + +guint8 spice_usb_device_get_state(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->state; +} + +static +gboolean _usbdk_hider_prepare(SpiceUsbDeviceManager *manager) +{ + SpiceUsbDeviceManagerPrivate *priv = manager->priv; + + g_return_val_if_fail(!priv->use_usbclerk, FALSE); + + if (priv->usbdk_hider_handle == NULL) { + priv->usbdk_hider_handle = usbdk_create_hider_handle(priv->usbdk_api); + if (priv->usbdk_hider_handle == NULL) { + g_warning("Failed to instantiate UsbDk hider interface"); + return FALSE; + } + } + + return TRUE; +} + +static +void _usbdk_hider_clear(SpiceUsbDeviceManager *manager) +{ + SpiceUsbDeviceManagerPrivate *priv = manager->priv; + + g_return_if_fail(!priv->use_usbclerk); + + if (priv->usbdk_hider_handle != NULL) { + usbdk_clear_hide_rules(priv->usbdk_api, priv->usbdk_hider_handle); + usbdk_close_hider_handle(priv->usbdk_api, priv->usbdk_hider_handle); + priv->usbdk_hider_handle = NULL; + } +} + +static +void _usbdk_hider_update(SpiceUsbDeviceManager *manager) +{ + SpiceUsbDeviceManagerPrivate *priv = manager->priv; + + g_return_if_fail(!priv->use_usbclerk); + + if (priv->auto_connect_filter == NULL) { + SPICE_DEBUG("No autoredirect rules, no hider setup needed"); + _usbdk_hider_clear(manager); + return; + } + + if (!priv->auto_connect) { + SPICE_DEBUG("Auto-connect disabled, no hider setup needed"); + _usbdk_hider_clear(manager); + return; + } + + if(_usbdk_hider_prepare(manager)) { + usbdk_api_set_hide_rules(priv->usbdk_api, + priv->usbdk_hider_handle, + priv->auto_connect_filter); + } +} + +#endif + +static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, NULL); + g_atomic_int_inc(&info->ref); + return device; +} + +static void spice_usb_device_unref(SpiceUsbDevice *device) +{ + gboolean ref_count_is_0; + + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_if_fail(info != NULL); + + ref_count_is_0 = g_atomic_int_dec_and_test(&info->ref); + if (ref_count_is_0) { +#ifndef G_OS_WIN32 + libusb_unref_device(info->libdev); +#endif + g_free(info); + } +} + +#ifndef G_OS_WIN32 /* Linux -- directly compare libdev */ +static gboolean +spice_usb_manager_device_equal_libdev(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, + libusb_device *libdev) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + if ((device == NULL) || (libdev == NULL)) + return FALSE; + + return info->libdev == libdev; +} +#else /* Windows -- compare vid:pid of device and libdev */ +static gboolean +spice_usb_manager_device_equal_libdev(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, + libusb_device *libdev) +{ + int busnum, devaddr; + + if ((device == NULL) || (libdev == NULL)) + return FALSE; + + if (manager->priv->use_usbclerk) { + busnum = spice_usb_device_get_vid(device); + devaddr = spice_usb_device_get_pid(device); + } else { + busnum = spice_usb_device_get_busnum(device); + devaddr = spice_usb_device_get_devaddr(device); + } + + return spice_usb_device_manager_libdev_match(manager, libdev, + busnum, devaddr); +} +#endif + +/* + * Caller must libusb_unref_device the libusb_device returned by this function. + * Returns a libusb_device, or NULL upon failure + */ +static libusb_device * +spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device) +{ +#ifdef G_OS_WIN32 + /* + * On win32 we need to do this the hard and slow way, by asking libusb to + * re-enumerate all devices and then finding a matching device. + * We cannot cache the libusb_device like we do under Linux since the + * driver swap we do under windows invalidates the cached libdev. + */ + + libusb_device *d, **devlist; + int i; + + g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), NULL); + g_return_val_if_fail(device != NULL, NULL); + g_return_val_if_fail(self->priv != NULL, NULL); + g_return_val_if_fail(self->priv->context != NULL, NULL); + + libusb_get_device_list(self->priv->context, &devlist); + if (!devlist) + return NULL; + + for (i = 0; (d = devlist[i]) != NULL; i++) { + if (spice_usb_manager_device_equal_libdev(self, device, d)) { + libusb_ref_device(d); + break; + } + } + + libusb_free_device_list(devlist, 1); + + return d; + +#else + /* Simply return a ref to the cached libdev */ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + return libusb_ref_device(info->libdev); +#endif +} +#endif /* USE_USBREDIR */ diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h new file mode 100644 index 0000000..6a8d0ac --- /dev/null +++ b/src/usb-device-manager.h @@ -0,0 +1,148 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011, 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_USB_DEVICE_MANAGER_H__ +#define __SPICE_USB_DEVICE_MANAGER_H__ + +#if !defined(__SPICE_CLIENT_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only <spice-client.h> can be included directly" +#endif + +#include "spice-client.h" +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define SPICE_TYPE_USB_DEVICE_MANAGER (spice_usb_device_manager_get_type ()) +#define SPICE_USB_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_USB_DEVICE_MANAGER, SpiceUsbDeviceManager)) +#define SPICE_USB_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_USB_DEVICE_MANAGER, SpiceUsbDeviceManagerClass)) +#define SPICE_IS_USB_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_USB_DEVICE_MANAGER)) +#define SPICE_IS_USB_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_USB_DEVICE_MANAGER)) +#define SPICE_USB_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_USB_DEVICE_MANAGER, SpiceUsbDeviceManagerClass)) + +#define SPICE_TYPE_USB_DEVICE (spice_usb_device_get_type()) + +typedef struct _SpiceUsbDeviceManager SpiceUsbDeviceManager; +typedef struct _SpiceUsbDeviceManagerClass SpiceUsbDeviceManagerClass; +typedef struct _SpiceUsbDeviceManagerPrivate SpiceUsbDeviceManagerPrivate; + +/** + * SpiceUsbDevice: + * + * The #SpiceUsbDevice struct is opaque and cannot be accessed directly. + */ +typedef struct _SpiceUsbDevice SpiceUsbDevice; + +/** + * SpiceUsbDeviceManager: + * + * The #SpiceUsbDeviceManager struct is opaque and should not be accessed directly. + */ +struct _SpiceUsbDeviceManager +{ + GObject parent; + + /*< private >*/ + SpiceUsbDeviceManagerPrivate *priv; + /* Do not add fields to this struct */ +}; + +/** + * SpiceUsbDeviceManagerClass: + * @parent_class: Parent class. + * @device_added: Signal class handler for the #SpiceUsbDeviceManager::device-added signal. + * @device_removed: Signal class handler for the #SpiceUsbDeviceManager::device-removed signal. + * @auto_connect_failed: Signal class handler for the #SpiceUsbDeviceManager::auto-connect-failed signal. + * @device_error: Signal class handler for the #SpiceUsbDeviceManager::device_error signal. + * + * Class structure for #SpiceUsbDeviceManager. + */ +struct _SpiceUsbDeviceManagerClass +{ + GObjectClass parent_class; + + /* signals */ + void (*device_added) (SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device); + void (*device_removed) (SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device); + void (*auto_connect_failed) (SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, GError *error); + void (*device_error) (SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, GError *error); + /*< private >*/ + /* + * If adding fields to this struct, remove corresponding + * amount of padding to avoid changing overall struct size + */ + gchar _spice_reserved[SPICE_RESERVED_PADDING]; +}; + +GType spice_usb_device_get_type(void); +GType spice_usb_device_manager_get_type(void); + +gchar *spice_usb_device_get_description(SpiceUsbDevice *device, const gchar *format); +gconstpointer spice_usb_device_get_libusb_device(const SpiceUsbDevice *device); + +SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session, + GError **err); + +GPtrArray *spice_usb_device_manager_get_devices(SpiceUsbDeviceManager *manager); +GPtrArray* spice_usb_device_manager_get_devices_with_filter( + SpiceUsbDeviceManager *manager, const gchar *filter); + +gboolean spice_usb_device_manager_is_device_connected(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device); +void spice_usb_device_manager_connect_device_async( + SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void spice_usb_device_manager_disconnect_device_async( + SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean spice_usb_device_manager_connect_device_finish( + SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err); + +gboolean spice_usb_device_manager_disconnect_device_finish( + SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err); + +#ifndef SPICE_DISABLE_DEPRECATED +SPICE_DEPRECATED +void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device); +#endif + +gboolean +spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GError **err); + +gboolean spice_usb_device_manager_is_redirecting(SpiceUsbDeviceManager *self); + +G_END_DECLS + +#endif /* __SPICE_USB_DEVICE_MANAGER_H__ */ diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c new file mode 100644 index 0000000..05c7054 --- /dev/null +++ b/src/usb-device-widget.c @@ -0,0 +1,614 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" +#include <glib/gi18n.h> +#include "spice-client.h" +#include "spice-marshal.h" +#include "usb-device-widget.h" + +/** + * SECTION:usb-device-widget + * @short_description: USB device selection widget + * @title: Spice USB device selection widget + * @section_id: + * @see_also: + * @stability: Stable + * @include: spice-client-gtk.h + * + * #SpiceUsbDeviceWidget is a gtk widget which apps can use to easily + * add an UI to select USB devices to redirect (or unredirect). + */ + +struct _SpiceUsbDeviceWidget +{ + GtkVBox parent; + + SpiceUsbDeviceWidgetPrivate *priv; +}; + +struct _SpiceUsbDeviceWidgetClass +{ + GtkVBoxClass parent_class; + + /* signals */ + void (*connect_failed) (SpiceUsbDeviceWidget *widget, + SpiceUsbDevice *device, GError *error); +}; + +/* ------------------------------------------------------------------ */ +/* Prototypes for callbacks */ +static void device_added_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, gpointer user_data); +static void device_removed_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, gpointer user_data); +static void device_error_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, GError *err, gpointer user_data); +static gboolean spice_usb_device_widget_update_status(gpointer user_data); + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_USB_DEVICE_WIDGET_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_USB_DEVICE_WIDGET, \ + SpiceUsbDeviceWidgetPrivate)) + +enum { + PROP_0, + PROP_SESSION, + PROP_DEVICE_FORMAT_STRING, +}; + +enum { + CONNECT_FAILED, + LAST_SIGNAL, +}; + +struct _SpiceUsbDeviceWidgetPrivate { + SpiceSession *session; + gchar *device_format_string; + SpiceUsbDeviceManager *manager; + GtkWidget *info_bar; + GtkWidget *label; + gchar *err_msg; + gsize device_count; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(SpiceUsbDeviceWidget, spice_usb_device_widget, GTK_TYPE_BOX); + +static void spice_usb_device_widget_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(gobject); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, priv->session); + break; + case PROP_DEVICE_FORMAT_STRING: + g_value_set_string(value, priv->device_format_string); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_usb_device_widget_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(gobject); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_SESSION: + priv->session = g_value_dup_object(value); + break; + case PROP_DEVICE_FORMAT_STRING: + priv->device_format_string = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_usb_device_widget_hide_info_bar(SpiceUsbDeviceWidget *self) +{ + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + + if (priv->info_bar) { + gtk_widget_destroy(priv->info_bar); + priv->info_bar = NULL; + } +} + +static void +spice_usb_device_widget_show_info_bar(SpiceUsbDeviceWidget *self, + const gchar *message, + GtkMessageType message_type, + const gchar *stock_icon_id) +{ + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + GtkWidget *info_bar, *content_area, *hbox, *widget; + + spice_usb_device_widget_hide_info_bar(self); + + info_bar = gtk_info_bar_new(); + gtk_info_bar_set_message_type(GTK_INFO_BAR(info_bar), message_type); + + content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar)); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_add(GTK_CONTAINER(content_area), hbox); + + widget = gtk_image_new_from_icon_name(stock_icon_id, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); + + widget = gtk_label_new(message); + gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0); + + priv->info_bar = gtk_alignment_new(0.0, 0.0, 1.0, 0.0); + gtk_alignment_set_padding(GTK_ALIGNMENT(priv->info_bar), 0, 0, 12, 0); + gtk_container_add(GTK_CONTAINER(priv->info_bar), info_bar); + gtk_box_pack_start(GTK_BOX(self), priv->info_bar, FALSE, FALSE, 0); + gtk_widget_show_all(priv->info_bar); +} + +static GObject *spice_usb_device_widget_constructor( + GType gtype, guint n_properties, GObjectConstructParam *properties) +{ + GObject *obj; + SpiceUsbDeviceWidget *self; + SpiceUsbDeviceWidgetPrivate *priv; + GPtrArray *devices = NULL; + GError *err = NULL; + gchar *str; + int i; + + { + /* Always chain up to the parent constructor */ + GObjectClass *parent_class; + parent_class = G_OBJECT_CLASS(spice_usb_device_widget_parent_class); + obj = parent_class->constructor(gtype, n_properties, properties); + } + + self = SPICE_USB_DEVICE_WIDGET(obj); + priv = self->priv; + if (!priv->session) + g_error("SpiceUsbDeviceWidget constructed without a session"); + + priv->label = gtk_label_new(NULL); + str = g_strdup_printf("<b>%s</b>", _("Select USB devices to redirect")); + gtk_label_set_markup(GTK_LABEL (priv->label), str); + g_free(str); + gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); + gtk_box_pack_start(GTK_BOX(self), priv->label, FALSE, FALSE, 0); + + priv->manager = spice_usb_device_manager_get(priv->session, &err); + if (err) { + spice_usb_device_widget_show_info_bar(self, err->message, + GTK_MESSAGE_WARNING, + "dialog-warning"); + g_clear_error(&err); + return obj; + } + + g_signal_connect(priv->manager, "device-added", + G_CALLBACK(device_added_cb), self); + g_signal_connect(priv->manager, "device-removed", + G_CALLBACK(device_removed_cb), self); + g_signal_connect(priv->manager, "device-error", + G_CALLBACK(device_error_cb), self); + + devices = spice_usb_device_manager_get_devices(priv->manager); + if (!devices) + goto end; + + for (i = 0; i < devices->len; i++) + device_added_cb(NULL, g_ptr_array_index(devices, i), self); + + g_ptr_array_unref(devices); + +end: + spice_usb_device_widget_update_status(self); + + return obj; +} + +static void spice_usb_device_widget_finalize(GObject *object) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(object); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + + if (priv->manager) { + g_signal_handlers_disconnect_by_func(priv->manager, + device_added_cb, self); + g_signal_handlers_disconnect_by_func(priv->manager, + device_removed_cb, self); + g_signal_handlers_disconnect_by_func(priv->manager, + device_error_cb, self); + } + g_object_unref(priv->session); + g_free(priv->device_format_string); + + if (G_OBJECT_CLASS(spice_usb_device_widget_parent_class)->finalize) + G_OBJECT_CLASS(spice_usb_device_widget_parent_class)->finalize(object); +} + +static void spice_usb_device_widget_class_init( + SpiceUsbDeviceWidgetClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (SpiceUsbDeviceWidgetPrivate)); + + gobject_class->constructor = spice_usb_device_widget_constructor; + gobject_class->finalize = spice_usb_device_widget_finalize; + gobject_class->get_property = spice_usb_device_widget_get_property; + gobject_class->set_property = spice_usb_device_widget_set_property; + + /** + * SpiceUsbDeviceWidget:session: + * + * #SpiceSession this #SpiceUsbDeviceWidget is associated with + * + **/ + pspec = g_param_spec_object("session", + "Session", + "SpiceSession", + SPICE_TYPE_SESSION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_SESSION, pspec); + + /** + * SpiceUsbDeviceWidget:device-format-string: + * + * Format string to pass to spice_usb_device_get_description() for getting + * the device USB descriptions. + */ + pspec = g_param_spec_string("device-format-string", + "Device format string", + "Format string for device description", + NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_property(gobject_class, PROP_DEVICE_FORMAT_STRING, + pspec); + + /** + * SpiceUsbDeviceWidget::connect-failed: + * @widget: The #SpiceUsbDeviceWidget that emitted the signal + * @device: #SpiceUsbDevice boxed object corresponding to the added device + * @error: #GError describing the reason why the connect failed + * + * The #SpiceUsbDeviceWidget::connect-failed signal is emitted whenever + * the user has requested for a device to be redirected and this has + * failed. + **/ + signals[CONNECT_FAILED] = + g_signal_new("connect-failed", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(SpiceUsbDeviceWidgetClass, connect_failed), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, + 2, + SPICE_TYPE_USB_DEVICE, + G_TYPE_ERROR); +} + +static void spice_usb_device_widget_init(SpiceUsbDeviceWidget *self) +{ + self->priv = SPICE_USB_DEVICE_WIDGET_GET_PRIVATE(self); +} + +/* ------------------------------------------------------------------ */ +/* public api */ + +/** + * spice_usb_device_widget_new: + * @session: #SpiceSession for which to widget will control USB redirection + * @device_format_string: (allow-none): String passed to + * spice_usb_device_get_description() + * + * Creates a new widget to control USB redirection. + * + * Returns: a new #SpiceUsbDeviceWidget instance + */ +GtkWidget *spice_usb_device_widget_new(SpiceSession *session, + const gchar *device_format_string) +{ + return g_object_new(SPICE_TYPE_USB_DEVICE_WIDGET, + "orientation", GTK_ORIENTATION_VERTICAL, + "session", session, + "device-format-string", device_format_string, + "spacing", 6, + NULL); +} + +/* ------------------------------------------------------------------ */ +/* callbacks */ + +static SpiceUsbDevice *get_usb_device(GtkWidget *widget) +{ + if (!GTK_IS_ALIGNMENT(widget)) + return NULL; + + widget = gtk_bin_get_child(GTK_BIN(widget)); + return g_object_get_data(G_OBJECT(widget), "usb-device"); +} + +static void check_can_redirect(GtkWidget *widget, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + SpiceUsbDevice *device; + gboolean can_redirect; + GError *err = NULL; + + device = get_usb_device(widget); + if (!device) + return; /* Non device widget, ie the info_bar */ + + priv->device_count++; + + if (spice_usb_device_manager_is_redirecting(priv->manager)) { + can_redirect = FALSE; + } else { + can_redirect = spice_usb_device_manager_can_redirect_device(priv->manager, + device, &err); + /* If we cannot redirect this device, append the error message to + err_msg, but only if it is *not* already there! */ + if (!can_redirect) { + if (priv->err_msg) { + if (!strstr(priv->err_msg, err->message)) { + gchar *old_err_msg = priv->err_msg; + priv->err_msg = g_strdup_printf("%s\n%s", priv->err_msg, + err->message); + g_free(old_err_msg); + } + } else { + priv->err_msg = g_strdup(err->message); + } + } + g_clear_error(&err); + } + gtk_widget_set_sensitive(widget, can_redirect); +} + +static gboolean spice_usb_device_widget_update_status(gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + gchar *str, *markup_str; + const gchar *free_channels_str; + int free_channels; + gboolean redirecting; + + redirecting = spice_usb_device_manager_is_redirecting(priv->manager); + + g_object_get(priv->manager, "free-channels", &free_channels, NULL); + free_channels_str = ngettext(_("Select USB devices to redirect (%d free channel)"), + _("Select USB devices to redirect (%d free channels)"), + free_channels); + str = g_strdup_printf(free_channels_str, free_channels); + markup_str = g_strdup_printf("<b>%s</b>", str); + gtk_label_set_markup(GTK_LABEL (priv->label), markup_str); + g_free(markup_str); + g_free(str); + + priv->device_count = 0; + gtk_container_foreach(GTK_CONTAINER(self), check_can_redirect, self); + + if (priv->err_msg) { + spice_usb_device_widget_show_info_bar(self, priv->err_msg, + GTK_MESSAGE_INFO, + "dialog-warning"); + g_free(priv->err_msg); + priv->err_msg = NULL; + } else if (redirecting) { + spice_usb_device_widget_show_info_bar(self, _("Redirecting USB Device..."), + GTK_MESSAGE_INFO, + "dialog-information"); + } else { + spice_usb_device_widget_hide_info_bar(self); + } + + if (priv->device_count == 0) + spice_usb_device_widget_show_info_bar(self, _("No USB devices detected"), + GTK_MESSAGE_INFO, + "dialog-information"); + return FALSE; +} + +typedef struct _connect_cb_data { + GtkWidget *check; + SpiceUsbDeviceWidget *self; +} connect_cb_data; + +static void connect_cb_data_free(connect_cb_data *data) +{ + spice_usb_device_widget_update_status(data->self); + g_object_unref(data->check); + g_object_unref(data->self); + g_free(data); +} + +static void _disconnect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data) +{ + SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject); + connect_cb_data *data = user_data; + GError *err = NULL; + + spice_usb_device_manager_disconnect_device_finish(manager, res, &err); + if (err) { + SPICE_DEBUG("Device disconnection failed"); + g_error_free(err); + } + + connect_cb_data_free(data); +} + +static void checkbox_clicked_cb(GtkWidget *check, gpointer user_data); +static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data) +{ + SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject); + connect_cb_data *data = user_data; + SpiceUsbDeviceWidget *self = data->self; + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + SpiceUsbDevice *device; + GError *err = NULL; + gchar *desc; + + spice_usb_device_manager_connect_device_finish(manager, res, &err); + if (err) { + device = g_object_get_data(G_OBJECT(data->check), "usb-device"); + desc = spice_usb_device_get_description(device, + priv->device_format_string); + g_prefix_error(&err, "Could not redirect %s: ", desc); + g_free(desc); + + SPICE_DEBUG("%s", err->message); + g_signal_emit(self, signals[CONNECT_FAILED], 0, device, err); + g_error_free(err); + + /* don't trigger a disconnect if connect failed */ + g_signal_handlers_block_by_func(GTK_TOGGLE_BUTTON(data->check), + checkbox_clicked_cb, self); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->check), FALSE); + g_signal_handlers_unblock_by_func(GTK_TOGGLE_BUTTON(data->check), + checkbox_clicked_cb, self); + } + + connect_cb_data_free(data); +} + +static void checkbox_clicked_cb(GtkWidget *check, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + SpiceUsbDevice *device; + + device = g_object_get_data(G_OBJECT(check), "usb-device"); + connect_cb_data *data = g_new(connect_cb_data, 1); + data->check = g_object_ref(check); + data->self = g_object_ref(self); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) { + spice_usb_device_manager_connect_device_async(priv->manager, + device, + NULL, + connect_cb, + data); + } else { + spice_usb_device_manager_disconnect_device_async(priv->manager, + device, + NULL, + _disconnect_cb, + data); + + } + spice_usb_device_widget_update_status(self); +} + +static void checkbox_usb_device_destroy_notify(gpointer data) +{ + g_boxed_free(spice_usb_device_get_type(), data); +} + +static void device_added_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + SpiceUsbDeviceWidgetPrivate *priv = self->priv; + GtkWidget *align, *check; + gchar *desc; + + desc = spice_usb_device_get_description(device, + priv->device_format_string); + check = gtk_check_button_new_with_label(desc); + g_free(desc); + + if (spice_usb_device_manager_is_device_connected(priv->manager, + device)) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); + + g_object_set_data_full( + G_OBJECT(check), "usb-device", + g_boxed_copy(spice_usb_device_get_type(), device), + checkbox_usb_device_destroy_notify); + g_signal_connect(G_OBJECT(check), "clicked", + G_CALLBACK(checkbox_clicked_cb), self); + + align = gtk_alignment_new(0, 0, 0, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0); + gtk_container_add(GTK_CONTAINER(align), check); + gtk_box_pack_end(GTK_BOX(self), align, FALSE, FALSE, 0); + spice_usb_device_widget_update_status(self); + gtk_widget_show_all(align); +} + +static void destroy_widget_by_usb_device(GtkWidget *widget, gpointer user_data) +{ + if (get_usb_device(widget) == user_data) + gtk_widget_destroy(widget); +} + +static void device_removed_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + + gtk_container_foreach(GTK_CONTAINER(self), + destroy_widget_by_usb_device, device); + + spice_usb_device_widget_update_status(self); +} + +static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data) +{ + if (get_usb_device(widget) == user_data) { + GtkWidget *check = gtk_bin_get_child(GTK_BIN(widget)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE); + } +} + +static void device_error_cb(SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, GError *err, gpointer user_data) +{ + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); + + gtk_container_foreach(GTK_CONTAINER(self), + set_inactive_by_usb_device, device); + + spice_usb_device_widget_update_status(self); +} diff --git a/src/usb-device-widget.h b/src/usb-device-widget.h new file mode 100644 index 0000000..a4ba638 --- /dev/null +++ b/src/usb-device-widget.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_USB_DEVICE_WIDGET_H__ +#define __SPICE_USB_DEVICE_WIDGET_H__ + +#if !defined(__SPICE_CLIENT_GTK_H_INSIDE__) && !defined(SPICE_COMPILATION) +#warning "Only <spice-client-gtk.h> can be included directly" +#endif + +#include <gtk/gtk.h> +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_USB_DEVICE_WIDGET (spice_usb_device_widget_get_type ()) +#define SPICE_USB_DEVICE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_USB_DEVICE_WIDGET, SpiceUsbDeviceWidget)) +#define SPICE_USB_DEVICE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_USB_DEVICE_WIDGET, SpiceUsbDeviceWidgetClass)) +#define SPICE_IS_USB_DEVICE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_USB_DEVICE_WIDGET)) +#define SPICE_IS_USB_DEVICE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_USB_DEVICE_WIDGET)) +#define SPICE_USB_DEVICE_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_USB_DEVICE_WIDGET, SpiceUsbDeviceWidgetClass)) + +typedef struct _SpiceUsbDeviceWidget SpiceUsbDeviceWidget; +typedef struct _SpiceUsbDeviceWidgetClass SpiceUsbDeviceWidgetClass; +typedef struct _SpiceUsbDeviceWidgetPrivate SpiceUsbDeviceWidgetPrivate; + +GType spice_usb_device_widget_get_type(void); +GtkWidget *spice_usb_device_widget_new(SpiceSession *session, + const gchar *device_format_string); + +G_END_DECLS + +#endif /* __SPICE_USB_DEVICE_WIDGET_H__ */ diff --git a/src/usbdk_api.c b/src/usbdk_api.c new file mode 100644 index 0000000..f5009e5 --- /dev/null +++ b/src/usbdk_api.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + + Authors: + Dmitry Fleytman <dmitry@daynix.com> + Kirill Moizik <kirill@daynix.com> +*/ +#include <config.h> + +#include <windows.h> +#include <glib-object.h> +#include "usbdk_api.h" +#include "channel-usbredir-priv.h" + +#define USB_DK_HIDE_RULE_MATCH_ALL ((ULONG64)(-1)) +typedef struct tag_USB_DK_HIDE_RULE +{ + ULONG64 Hide; + ULONG64 Class; + ULONG64 VID; + ULONG64 PID; + ULONG64 BCD; +} USB_DK_HIDE_RULE, *PUSB_DK_HIDE_RULE; + +typedef HANDLE(__cdecl *USBDK_CREATEHIDERHANDLE)(void); +typedef BOOL(__cdecl * USBDK_ADDHIDERULE)(HANDLE hider_handle, PUSB_DK_HIDE_RULE rule); +typedef BOOL(__cdecl *USBDK_CLEARHIDERULES)(HANDLE hider_handle); +typedef void(__cdecl *USBDK_CLOSEHIDERHANDLE)(HANDLE hider_handle); + +struct tag_usbdk_api_wrapper +{ + HMODULE module; + USBDK_CREATEHIDERHANDLE CreateHiderHandle; + USBDK_ADDHIDERULE AddRule; + USBDK_CLEARHIDERULES ClearRules; + USBDK_CLOSEHIDERHANDLE CloseHiderHandle; +}; + +BOOL usbdk_is_driver_installed(void) +{ + gboolean usbdk_installed = FALSE; + SC_HANDLE managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + + if (managerHandle) { + SC_HANDLE serviceHandle = OpenService(managerHandle, TEXT("UsbDk"), GENERIC_READ); + + if (serviceHandle) { + SPICE_DEBUG("UsbDk driver is installed."); + usbdk_installed = TRUE; + CloseServiceHandle(serviceHandle); + } + CloseServiceHandle(managerHandle); + } + return usbdk_installed; +} + +void usbdk_api_unload(usbdk_api_wrapper *usbdk_api) +{ + if (usbdk_api != NULL) { + if (usbdk_api->module != NULL) { + SPICE_DEBUG("Unloading UsbDk API DLL"); + FreeLibrary(usbdk_api->module); + } + g_free(usbdk_api); + } +} + +usbdk_api_wrapper *usbdk_api_load(void) +{ + usbdk_api_wrapper *usbdk_api = g_new0(usbdk_api_wrapper, 1); + + SPICE_DEBUG("Loading UsbDk API DLL"); + usbdk_api->module = LoadLibraryA("UsbDkHelper"); + if (usbdk_api->module == NULL) { + g_warning("Failed to load UsbDkHelper.dll, error %lu", GetLastError()); + goto error_unload; + } + + usbdk_api->CreateHiderHandle = (USBDK_CREATEHIDERHANDLE) + GetProcAddress(usbdk_api->module, "UsbDk_CreateHiderHandle"); + if (usbdk_api->CreateHiderHandle == NULL) { + g_warning("Failed to find CreateHandle entry point"); + goto error_unload; + } + + usbdk_api->AddRule = (USBDK_ADDHIDERULE) + GetProcAddress(usbdk_api->module, "UsbDk_AddHideRule"); + if (usbdk_api->AddRule == NULL) { + g_warning("Failed to find AddRule entry point"); + goto error_unload; + } + + usbdk_api->ClearRules = (USBDK_CLEARHIDERULES) + GetProcAddress(usbdk_api->module, "UsbDk_ClearHideRules"); + if (usbdk_api->ClearRules == NULL) { + g_warning("Failed to find ClearRules entry point"); + goto error_unload; + } + + usbdk_api->CloseHiderHandle = (USBDK_CLOSEHIDERHANDLE) + GetProcAddress(usbdk_api->module, "UsbDk_CloseHiderHandle"); + if (usbdk_api->CloseHiderHandle == NULL) { + g_warning("Failed to find CloseHiderHandle entry point"); + goto error_unload; + } + return usbdk_api; + +error_unload: + usbdk_api_unload(usbdk_api); + return NULL; +} + +static uint64_t usbdk_usbredir_field_to_usbdk(int value) +{ + if (value >= 0) { + return value; + } + + g_warn_if_fail(value == -1); + + return USB_DK_HIDE_RULE_MATCH_ALL; +} + +static BOOL usbdk_add_hide_rule(usbdk_api_wrapper *usbdk_api, + HANDLE hider_handle, + PUSB_DK_HIDE_RULE rule) +{ + return usbdk_api->AddRule(hider_handle, rule); +} + +void usbdk_api_set_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle, + gchar *redirect_on_connect) +{ + struct usbredirfilter_rule *rules; + int r, count; + + r = usbredirfilter_string_to_rules(redirect_on_connect, ",", "|", + &rules, &count); + if (r) { + g_warning("auto-connect rules parsing failed with error %d", r); + return; + } + + for (int i = 0; i < count; i++) { + USB_DK_HIDE_RULE rule; + rule.Hide = usbdk_usbredir_field_to_usbdk(rules[i].allow); + rule.Class = usbdk_usbredir_field_to_usbdk(rules[i].device_class); + rule.VID = usbdk_usbredir_field_to_usbdk(rules[i].vendor_id); + rule.PID = usbdk_usbredir_field_to_usbdk(rules[i].product_id); + rule.BCD = usbdk_usbredir_field_to_usbdk(rules[i].device_version_bcd); + if (!usbdk_add_hide_rule(usbdk_api, hider_handle, &rule)) { + SPICE_DEBUG("UsbDk add hide rule API failed"); + } + } + + free(rules); +} + +HANDLE usbdk_create_hider_handle(usbdk_api_wrapper *usbdk_api) +{ + HANDLE handle = usbdk_api->CreateHiderHandle(); + return (handle == INVALID_HANDLE_VALUE) ? NULL : handle; +} + +BOOL usbdk_clear_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle) +{ + return usbdk_api->ClearRules(hider_handle); +} + +void usbdk_close_hider_handle(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle) +{ + return usbdk_api->CloseHiderHandle(hider_handle); +} diff --git a/src/usbdk_api.h b/src/usbdk_api.h new file mode 100644 index 0000000..8e5406c --- /dev/null +++ b/src/usbdk_api.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + + Authors: + Dmitry Fleytman <dmitry@daynix.com> + Kirill Moizik <kirill@daynix.com> +*/ +#ifndef USBDK_HEADER +#define USBDK_HEADER + +typedef struct tag_usbdk_api_wrapper usbdk_api_wrapper; + +usbdk_api_wrapper *usbdk_api_load(void); +void usbdk_api_unload(usbdk_api_wrapper *usbdk_api); +BOOL usbdk_is_driver_installed(void); +HANDLE usbdk_create_hider_handle(usbdk_api_wrapper *usbdk_api); +void usbdk_api_set_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle, gchar *redirect_on_connect); +BOOL usbdk_clear_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle); +void usbdk_close_hider_handle(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle); +#endif diff --git a/src/usbutil.c b/src/usbutil.c new file mode 100644 index 0000000..6dcb4de --- /dev/null +++ b/src/usbutil.c @@ -0,0 +1,321 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <glib-object.h> +#include <glib/gi18n.h> +#include <ctype.h> +#include <stdlib.h> + +#ifdef USE_USBREDIR +#ifdef __linux__ +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#endif +#include "usbutil.h" +#include "spice-util-priv.h" + +#define VENDOR_NAME_LEN (122 - sizeof(void *)) +#define PRODUCT_NAME_LEN 126 + +typedef struct _usb_product_info { + guint16 product_id; + char name[PRODUCT_NAME_LEN]; +} usb_product_info; + +typedef struct _usb_vendor_info { + usb_product_info *product_info; + int product_count; + guint16 vendor_id; + char name[VENDOR_NAME_LEN]; +} usb_vendor_info; + +static GMutex usbids_load_mutex; +static int usbids_vendor_count = 0; /* < 0: failed, 0: empty, > 0: loaded */ +static usb_vendor_info *usbids_vendor_info = NULL; + +G_GNUC_INTERNAL +const char *spice_usbutil_libusb_strerror(enum libusb_error error_code) +{ + switch (error_code) { + case LIBUSB_SUCCESS: + return "Success"; + case LIBUSB_ERROR_IO: + return "Input/output error"; + case LIBUSB_ERROR_INVALID_PARAM: + return "Invalid parameter"; + case LIBUSB_ERROR_ACCESS: + return "Access denied (insufficient permissions)"; + case LIBUSB_ERROR_NO_DEVICE: + return "No such device (it may have been disconnected)"; + case LIBUSB_ERROR_NOT_FOUND: + return "Entity not found"; + case LIBUSB_ERROR_BUSY: + return "Resource busy"; + case LIBUSB_ERROR_TIMEOUT: + return "Operation timed out"; + case LIBUSB_ERROR_OVERFLOW: + return "Overflow"; + case LIBUSB_ERROR_PIPE: + return "Pipe error"; + case LIBUSB_ERROR_INTERRUPTED: + return "System call interrupted (perhaps due to signal)"; + case LIBUSB_ERROR_NO_MEM: + return "Insufficient memory"; + case LIBUSB_ERROR_NOT_SUPPORTED: + return "Operation not supported or unimplemented on this platform"; + case LIBUSB_ERROR_OTHER: + return "Other error"; + } + return "Unknown error"; +} + +#ifdef __linux__ +/* <Sigh> libusb does not allow getting the manufacturer and product strings + without opening the device, so grab them directly from sysfs */ +static gchar *spice_usbutil_get_sysfs_attribute(int bus, int address, + const char *attribute) +{ + struct stat stat_buf; + char filename[256]; + gchar *contents; + + snprintf(filename, sizeof(filename), "/dev/bus/usb/%03d/%03d", + bus, address); + if (stat(filename, &stat_buf) != 0) + return NULL; + + snprintf(filename, sizeof(filename), "/sys/dev/char/%u:%u/%s", + major(stat_buf.st_rdev), minor(stat_buf.st_rdev), attribute); + if (!g_file_get_contents(filename, &contents, NULL, NULL)) + return NULL; + + /* Remove the newline at the end */ + contents[strlen(contents) - 1] = '\0'; + + return contents; +} +#endif + +static gboolean spice_usbutil_parse_usbids(gchar *path) +{ + gchar *contents, *line, **lines; + usb_product_info *product_info; + int i, j, id, product_count = 0; + + usbids_vendor_count = 0; + if (!g_file_get_contents(path, &contents, NULL, NULL)) { + usbids_vendor_count = -1; + return FALSE; + } + + lines = g_strsplit(contents, "\n", -1); + + for (i = 0; lines[i]; i++) { + if (!isxdigit(lines[i][0]) || !isxdigit(lines[i][1])) + continue; + + for (j = 1; lines[i + j] && + (lines[i + j][0] == '\t' || + lines[i + j][0] == '#' || + lines[i + j][0] == '\0'); j++) { + if (lines[i + j][0] == '\t' && isxdigit(lines[i + j][1])) + product_count++; + } + i += j - 1; + + usbids_vendor_count++; + } + + usbids_vendor_info = g_new(usb_vendor_info, usbids_vendor_count); + product_info = g_new(usb_product_info, product_count); + + usbids_vendor_count = 0; + for (i = 0; lines[i]; i++) { + line = lines[i]; + + if (!isxdigit(line[0]) || !isxdigit(line[1])) + continue; + + id = strtoul(line, &line, 16); + while (isspace(line[0])) + line++; + + usbids_vendor_info[usbids_vendor_count].vendor_id = id; + snprintf(usbids_vendor_info[usbids_vendor_count].name, + VENDOR_NAME_LEN, "%s", line); + + product_count = 0; + for (j = 1; lines[i + j] && + (lines[i + j][0] == '\t' || + lines[i + j][0] == '#' || + lines[i + j][0] == '\0'); j++) { + line = lines[i + j]; + + if (line[0] != '\t' || !isxdigit(line[1])) + continue; + + id = strtoul(line + 1, &line, 16); + while (isspace(line[0])) + line++; + product_info[product_count].product_id = id; + snprintf(product_info[product_count].name, + PRODUCT_NAME_LEN, "%s", line); + + product_count++; + } + i += j - 1; + + usbids_vendor_info[usbids_vendor_count].product_count = product_count; + usbids_vendor_info[usbids_vendor_count].product_info = product_info; + product_info += product_count; + usbids_vendor_count++; + } + + g_strfreev(lines); + g_free(contents); + +#if 0 /* Testing only */ + for (i = 0; i < usbids_vendor_count; i++) { + printf("%04x %s\n", usbids_vendor_info[i].vendor_id, + usbids_vendor_info[i].name); + product_info = usbids_vendor_info[i].product_info; + for (j = 0; j < usbids_vendor_info[i].product_count; j++) { + printf("\t%04x %s\n", product_info[j].product_id, + product_info[j].name); + } + } +#endif + + return TRUE; +} + +static gboolean spice_usbutil_load_usbids(void) +{ + gboolean success = FALSE; + + g_mutex_lock(&usbids_load_mutex); + if (usbids_vendor_count) { + success = usbids_vendor_count > 0; + goto leave; + } + +#ifdef WITH_USBIDS + success = spice_usbutil_parse_usbids(USB_IDS); +#else + { + const gchar * const *dirs = g_get_system_data_dirs(); + gchar *path = NULL; + int i; + + for (i = 0; dirs[i]; ++i) { + path = g_build_filename(dirs[i], "hwdata", "usb.ids", NULL); + success = spice_usbutil_parse_usbids(path); + SPICE_DEBUG("loading %s success: %s", path, spice_yes_no(success)); + g_free(path); + + if (success) + goto leave; + } + } +#endif + +leave: + g_mutex_unlock(&usbids_load_mutex); + return success; +} + +G_GNUC_INTERNAL +void spice_usb_util_get_device_strings(int bus, int address, + int vendor_id, int product_id, + gchar **manufacturer, gchar **product) +{ + usb_product_info *product_info; + int i, j; + + g_return_if_fail(manufacturer != NULL); + g_return_if_fail(product != NULL); + + *manufacturer = NULL; + *product = NULL; + +#if __linux__ + *manufacturer = spice_usbutil_get_sysfs_attribute(bus, address, "manufacturer"); + *product = spice_usbutil_get_sysfs_attribute(bus, address, "product"); +#endif + + if ((!*manufacturer || !*product) && + spice_usbutil_load_usbids()) { + + for (i = 0; i < usbids_vendor_count; i++) { + if ((int)usbids_vendor_info[i].vendor_id != vendor_id) + continue; + + if (!*manufacturer && usbids_vendor_info[i].name[0]) + *manufacturer = g_strdup(usbids_vendor_info[i].name); + + product_info = usbids_vendor_info[i].product_info; + for (j = 0; j < usbids_vendor_info[i].product_count; j++) { + if ((int)product_info[j].product_id != product_id) + continue; + + if (!*product && product_info[j].name[0]) + *product = g_strdup(product_info[j].name); + + break; + } + break; + } + } + + if (!*manufacturer) + *manufacturer = g_strdup(_("USB")); + if (!*product) + *product = g_strdup(_("Device")); + + /* Some devices have unwanted whitespace in their strings */ + g_strstrip(*manufacturer); + g_strstrip(*product); + + /* Some devices repeat the manufacturer at the beginning of product */ + if (g_str_has_prefix(*product, *manufacturer) && + strlen(*product) > strlen(*manufacturer)) { + gchar *tmp = g_strdup(*product + strlen(*manufacturer)); + g_free(*product); + *product = tmp; + g_strstrip(*product); + } +} + +#endif + +#ifdef USBUTIL_TEST +int main() +{ + if (spice_usbutil_load_usbids()) + exit(0); + + exit(1); +} +#endif diff --git a/src/usbutil.h b/src/usbutil.h new file mode 100644 index 0000000..de5e92a --- /dev/null +++ b/src/usbutil.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_USBUTIL_H__ +#define __SPICE_USBUTIL_H__ + +#include <glib.h> + +#ifdef USE_USBREDIR +#include <libusb.h> + +G_BEGIN_DECLS + +const char *spice_usbutil_libusb_strerror(enum libusb_error error_code); +void spice_usb_util_get_device_strings(int bus, int address, + int vendor_id, int product_id, + gchar **manufacturer, gchar **product); + +G_END_DECLS + +#endif /* USE_USBREDIR */ +#endif /* __SPICE_USBUTIL_H__ */ diff --git a/src/vmcstream.c b/src/vmcstream.c new file mode 100644 index 0000000..c536f71 --- /dev/null +++ b/src/vmcstream.c @@ -0,0 +1,523 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#include "config.h" + +#include <string.h> + +#include "vmcstream.h" +#include "spice-channel-priv.h" +#include "gio-coroutine.h" + +struct _SpiceVmcInputStream +{ + GInputStream parent_instance; + GTask *task; + struct coroutine *coroutine; + + SpiceChannel *channel; + gboolean all; + guint8 *buffer; + gsize count; + gsize pos; + + gulong cancel_id; +}; + +struct _SpiceVmcInputStreamClass +{ + GInputStreamClass parent_class; +}; + +static gssize spice_vmc_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); +static void spice_vmc_input_stream_read_async (GInputStream *stream, + void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +static gssize spice_vmc_input_stream_read_finish (GInputStream *stream, + GAsyncResult *result, + GError **error); +static gssize spice_vmc_input_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error); +static gboolean spice_vmc_input_stream_close (GInputStream *stream, + GCancellable *cancellable, + GError **error); + +G_DEFINE_TYPE(SpiceVmcInputStream, spice_vmc_input_stream, G_TYPE_INPUT_STREAM) + + +static void +spice_vmc_input_stream_class_init(SpiceVmcInputStreamClass *klass) +{ + GInputStreamClass *istream_class; + + istream_class = G_INPUT_STREAM_CLASS(klass); + istream_class->read_fn = spice_vmc_input_stream_read; + istream_class->read_async = spice_vmc_input_stream_read_async; + istream_class->read_finish = spice_vmc_input_stream_read_finish; + istream_class->skip = spice_vmc_input_stream_skip; + istream_class->close_fn = spice_vmc_input_stream_close; +} + +static void +spice_vmc_input_stream_init(SpiceVmcInputStream *self) +{ +} + +static SpiceVmcInputStream * +spice_vmc_input_stream_new(void) +{ + SpiceVmcInputStream *self; + + self = g_object_new(SPICE_TYPE_VMC_INPUT_STREAM, NULL); + + return self; +} + +typedef struct _complete_in_idle_cb_data { + GTask *task; + gssize pos; +} complete_in_idle_cb_data; + +static gboolean +complete_in_idle_cb(gpointer user_data) +{ + complete_in_idle_cb_data *data = user_data; + + g_task_return_int(data->task, data->pos); + + g_object_unref (data->task); + g_free (data); + + return FALSE; +} + +/* coroutine */ +/* + * Feed a SpiceVmc stream with new data from a coroutine + * + * The other end will be waiting on read_async() until data is fed + * here. + */ +G_GNUC_INTERNAL void +spice_vmc_input_stream_co_data(SpiceVmcInputStream *self, + const gpointer d, gsize size) +{ + guint8 *data = d; + + g_return_if_fail(SPICE_IS_VMC_INPUT_STREAM(self)); + g_return_if_fail(self->coroutine == NULL); + + self->coroutine = coroutine_self(); + + while (size > 0) { + complete_in_idle_cb_data *cb_data; + + SPICE_DEBUG("spicevmc co_data %p", self->task); + if (!self->task) + coroutine_yield(NULL); + + g_return_if_fail(self->task != NULL); + + gsize min = MIN(self->count, size); + memcpy(self->buffer, data, min); + + size -= min; + data += min; + + SPICE_DEBUG("spicevmc co_data complete: %" G_GSIZE_FORMAT + "/%" G_GSIZE_FORMAT, min, self->count); + + self->pos += min; + self->buffer += min; + + if (self->all && min > 0 && self->pos != self->count) + continue; + + /* Let's deal with the task complete in idle by ourselves, as GTask + * heuristic only makes sense in a non-coroutine case. + */ + cb_data = g_new(complete_in_idle_cb_data , 1); + cb_data->task = g_object_ref(self->task); + cb_data->pos = self->pos; + g_idle_add(complete_in_idle_cb, cb_data); + + g_cancellable_disconnect(g_task_get_cancellable(self->task), self->cancel_id); + g_clear_object(&self->task); + } + + self->coroutine = NULL; +} + +static void +read_cancelled(GCancellable *cancellable, + gpointer user_data) +{ + SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(user_data); + + SPICE_DEBUG("read cancelled, %p", self->task); + g_task_return_new_error(self->task, + G_IO_ERROR, G_IO_ERROR_CANCELLED, + "read cancelled"); + + /* With GTask, we don't need to disconnect GCancellable when task is + * cancelled within cancellable callback as it could lead to deadlocks + * e.g: https://bugzilla.gnome.org/show_bug.cgi?id=705395 */ + g_clear_object(&self->task); +} + +G_GNUC_INTERNAL void +spice_vmc_input_stream_read_all_async(GInputStream *stream, + void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream); + GTask *task; + + /* no concurrent read permitted by ginputstream */ + g_return_if_fail(self->task == NULL); + self->all = TRUE; + self->buffer = buffer; + self->count = count; + self->pos = 0; + task = g_task_new(self, + cancellable, + callback, + user_data); + self->task = task; + if (cancellable) + self->cancel_id = + g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), self, NULL); + + if (self->coroutine) + coroutine_yieldto(self->coroutine, NULL); +} + +G_GNUC_INTERNAL gssize +spice_vmc_input_stream_read_all_finish(GInputStream *stream, + GAsyncResult *result, + GError **error) +{ + GTask *task = G_TASK(result); + SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream); + GCancellable *cancel; + + g_return_val_if_fail(g_task_is_valid(task, self), -1); + cancel = g_task_get_cancellable(task); + if (!g_cancellable_is_cancelled(cancel)) { + g_cancellable_disconnect(cancel, self->cancel_id); + self->cancel_id = 0; + } + return g_task_propagate_int(task, error); +} + +static void +spice_vmc_input_stream_read_async(GInputStream *stream, + void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream); + GTask *task; + + /* no concurrent read permitted by ginputstream */ + g_return_if_fail(self->task == NULL); + self->all = FALSE; + self->buffer = buffer; + self->count = count; + self->pos = 0; + + task = g_task_new(self, cancellable, callback, user_data); + self->task = task; + if (cancellable) + self->cancel_id = + g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), self, NULL); + + if (self->coroutine) + coroutine_yieldto(self->coroutine, NULL); +} + +static gssize +spice_vmc_input_stream_read_finish(GInputStream *stream, + GAsyncResult *result, + GError **error) +{ + GTask *task = G_TASK(result); + SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream); + GCancellable *cancel; + + g_return_val_if_fail(g_task_is_valid(task, self), -1); + + cancel = g_task_get_cancellable(task); + if (!g_cancellable_is_cancelled(cancel)) { + g_cancellable_disconnect(cancel, self->cancel_id); + self->cancel_id = 0; + } + return g_task_propagate_int(task, error); +} + +static gssize +spice_vmc_input_stream_read(GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_reached(-1); +} + +static gssize +spice_vmc_input_stream_skip(GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_reached(-1); +} + +static gboolean +spice_vmc_input_stream_close(GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + SPICE_DEBUG("fake close"); + return TRUE; +} + +/* OUTPUT */ + +struct _SpiceVmcOutputStream +{ + GOutputStream parent_instance; + + SpiceChannel *channel; /* weak */ +}; + +struct _SpiceVmcOutputStreamClass +{ + GOutputStreamClass parent_class; +}; + +static gssize spice_vmc_output_stream_write_fn (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); +static gssize spice_vmc_output_stream_write_finish (GOutputStream *stream, + GAsyncResult *result, + GError **error); +static void spice_vmc_output_stream_write_async (GOutputStream *stream, + const void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +G_DEFINE_TYPE(SpiceVmcOutputStream, spice_vmc_output_stream, G_TYPE_OUTPUT_STREAM) + + +static void +spice_vmc_output_stream_class_init(SpiceVmcOutputStreamClass *klass) +{ + GOutputStreamClass *ostream_class; + + ostream_class = G_OUTPUT_STREAM_CLASS(klass); + ostream_class->write_fn = spice_vmc_output_stream_write_fn; + ostream_class->write_async = spice_vmc_output_stream_write_async; + ostream_class->write_finish = spice_vmc_output_stream_write_finish; +} + +static void +spice_vmc_output_stream_init(SpiceVmcOutputStream *self) +{ +} + +static SpiceVmcOutputStream * +spice_vmc_output_stream_new(SpiceChannel *channel) +{ + SpiceVmcOutputStream *self; + + self = g_object_new(SPICE_TYPE_VMC_OUTPUT_STREAM, NULL); + self->channel = channel; + + return self; +} + +static gssize +spice_vmc_output_stream_write_fn(GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SpiceVmcOutputStream *self = SPICE_VMC_OUTPUT_STREAM(stream); + SpiceMsgOut *msg_out; + + msg_out = spice_msg_out_new(SPICE_CHANNEL(self->channel), + SPICE_MSGC_SPICEVMC_DATA); + spice_marshaller_add(msg_out->marshaller, buffer, count); + spice_msg_out_send(msg_out); + + return count; +} + +static gssize +spice_vmc_output_stream_write_finish(GOutputStream *stream, + GAsyncResult *simple, + GError **error) +{ + SpiceVmcOutputStream *self = SPICE_VMC_OUTPUT_STREAM(stream); + GAsyncResult *res = g_task_propagate_pointer(G_TASK(simple), error); + + SPICE_DEBUG("spicevmc write finish"); + return spice_vmc_write_finish(self->channel, res, error); +} + +static void +write_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GTask *task = user_data; + + g_task_return_pointer(task, g_object_ref(task), g_object_unref); + + g_object_unref(task); +} + +static void +spice_vmc_output_stream_write_async(GOutputStream *stream, + const void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SpiceVmcOutputStream *self = SPICE_VMC_OUTPUT_STREAM(stream); + GTask *task; + + SPICE_DEBUG("spicevmc write async"); + /* an AsyncResult to forward async op to channel */ + task = g_task_new(self, cancellable, callback, user_data); + + spice_vmc_write_async(self->channel, buffer, count, + cancellable, write_cb, + task); +} + +/* STREAM */ + +struct _SpiceVmcStream +{ + GIOStream parent_instance; + + SpiceChannel *channel; /* weak */ + SpiceVmcInputStream *in; + SpiceVmcOutputStream *out; +}; + +struct _SpiceVmcStreamClass +{ + GIOStreamClass parent_class; +}; + +static void spice_vmc_stream_finalize (GObject *object); +static GInputStream * spice_vmc_stream_get_input_stream (GIOStream *stream); +static GOutputStream * spice_vmc_stream_get_output_stream (GIOStream *stream); + +G_DEFINE_TYPE(SpiceVmcStream, spice_vmc_stream, G_TYPE_IO_STREAM) + +static void +spice_vmc_stream_class_init(SpiceVmcStreamClass *klass) +{ + GObjectClass *object_class; + GIOStreamClass *iostream_class; + + object_class = G_OBJECT_CLASS(klass); + object_class->finalize = spice_vmc_stream_finalize; + + iostream_class = G_IO_STREAM_CLASS(klass); + iostream_class->get_input_stream = spice_vmc_stream_get_input_stream; + iostream_class->get_output_stream = spice_vmc_stream_get_output_stream; +} + +static void +spice_vmc_stream_finalize(GObject *object) +{ + SpiceVmcStream *self = SPICE_VMC_STREAM(object); + + g_clear_object(&self->in); + g_clear_object(&self->out); + + G_OBJECT_CLASS(spice_vmc_stream_parent_class)->finalize(object); +} + +static void +spice_vmc_stream_init(SpiceVmcStream *self) +{ +} + +G_GNUC_INTERNAL SpiceVmcStream * +spice_vmc_stream_new(SpiceChannel *channel) +{ + SpiceVmcStream *self; + + self = g_object_new(SPICE_TYPE_VMC_STREAM, NULL); + self->channel = channel; + + return self; +} + +static GInputStream * +spice_vmc_stream_get_input_stream(GIOStream *stream) +{ + SpiceVmcStream *self = SPICE_VMC_STREAM(stream); + + if (!self->in) + self->in = spice_vmc_input_stream_new(); + + return G_INPUT_STREAM(self->in); +} + +static GOutputStream * +spice_vmc_stream_get_output_stream(GIOStream *stream) +{ + SpiceVmcStream *self = SPICE_VMC_STREAM(stream); + + if (!self->out) + self->out = spice_vmc_output_stream_new(self->channel); + + return G_OUTPUT_STREAM(self->out); +} diff --git a/src/vmcstream.h b/src/vmcstream.h new file mode 100644 index 0000000..1316b77 --- /dev/null +++ b/src/vmcstream.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2013 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_VMC_STREAM_H__ +#define __SPICE_VMC_STREAM_H__ + +#include <gio/gio.h> + +#include "spice-types.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_VMC_INPUT_STREAM (spice_vmc_input_stream_get_type ()) +#define SPICE_VMC_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPICE_TYPE_VMC_INPUT_STREAM, SpiceVmcInputStream)) +#define SPICE_VMC_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPICE_TYPE_VMC_INPUT_STREAM, SpiceVmcInputStreamClass)) +#define SPICE_IS_VMC_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPICE_TYPE_VMC_INPUT_STREAM)) +#define SPICE_IS_VMC_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPICE_TYPE_VMC_INPUT_STREAM)) +#define SPICE_VMC_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SPICE_TYPE_VMC_INPUT_STREAM, SpiceVmcInputStreamClass)) + +typedef struct _SpiceVmcInputStreamClass SpiceVmcInputStreamClass; +typedef struct _SpiceVmcInputStream SpiceVmcInputStream; + +GType spice_vmc_input_stream_get_type (void) G_GNUC_CONST; +void spice_vmc_input_stream_co_data (SpiceVmcInputStream *input, + const gpointer data, + gsize size); + +void spice_vmc_input_stream_read_all_async(GInputStream *stream, + void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gssize spice_vmc_input_stream_read_all_finish(GInputStream *stream, + GAsyncResult *result, + GError **error); + + +#define SPICE_TYPE_VMC_OUTPUT_STREAM (spice_vmc_output_stream_get_type ()) +#define SPICE_VMC_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPICE_TYPE_VMC_OUTPUT_STREAM, SpiceVmcOutputStream)) +#define SPICE_VMC_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPICE_TYPE_VMC_OUTPUT_STREAM, SpiceVmcOutputStreamClass)) +#define SPICE_IS_VMC_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPICE_TYPE_VMC_OUTPUT_STREAM)) +#define SPICE_IS_VMC_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPICE_TYPE_VMC_OUTPUT_STREAM)) +#define SPICE_VMC_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SPICE_TYPE_VMC_OUTPUT_STREAM, SpiceVmcOutputStreamClass)) + +typedef struct _SpiceVmcOutputStreamClass SpiceVmcOutputStreamClass; +typedef struct _SpiceVmcOutputStream SpiceVmcOutputStream; + +GType spice_vmc_output_stream_get_type (void) G_GNUC_CONST; + +#define SPICE_TYPE_VMC_STREAM (spice_vmc_stream_get_type ()) +#define SPICE_VMC_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPICE_TYPE_VMC_STREAM, SpiceVmcStream)) +#define SPICE_VMC_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPICE_TYPE_VMC_STREAM, SpiceVmcStreamClass)) +#define SPICE_IS_VMC_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPICE_TYPE_VMC_STREAM)) +#define SPICE_IS_VMC_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPICE_TYPE_VMC_STREAM)) +#define SPICE_VMC_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SPICE_TYPE_VMC_STREAM, SpiceVmcStreamClass)) + +typedef struct _SpiceVmcStreamClass SpiceVmcStreamClass; +typedef struct _SpiceVmcStream SpiceVmcStream; + +GType spice_vmc_stream_get_type (void) G_GNUC_CONST; +SpiceVmcStream* spice_vmc_stream_new (SpiceChannel *channel); + +G_END_DECLS + +#endif /* __SPICE_VMC_STREAM_H__ */ diff --git a/src/vncdisplaykeymap.c b/src/vncdisplaykeymap.c new file mode 100644 index 0000000..c50f9f7 --- /dev/null +++ b/src/vncdisplaykeymap.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2008 Anthony Liguori <anthony@codemonkey.ws> + * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include "config.h" + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include "vncdisplaykeymap.h" + +#include "spice-util.h" + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "vnc-keymap" +#define VNC_DEBUG(message) SPICE_DEBUG(message); + +/* + * This table is taken from QEMU x_keymap.c, under the terms: + * + * Copyright (c) 2003 Fabrice Bellard + * + * 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. + */ + + +/* Compatability code to allow build on Gtk2 and Gtk3 */ +#ifndef GDK_Tab +#define GDK_Tab GDK_KEY_Tab +#endif + +/* keycode translation for sending ISO_Left_Send + * to vncserver + */ +static struct { + GdkKeymapKey *keys; + gint n_keys; + guint keyval; +} untranslated_keys[] = {{NULL, 0, GDK_Tab}}; + +static unsigned int ref_count_for_untranslated_keys = 0; + +#ifdef GDK_WINDOWING_WAYLAND +#include <gdk/gdkwayland.h> +#endif + +#ifdef GDK_WINDOWING_BROADWAY +#include <gdk/gdkbroadway.h> +#endif + +#if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND) +/* Xorg Linux + evdev (offset evdev keycodes) */ +#include "vncdisplaykeymap_xorgevdev2xtkbd.c" +#endif + +#ifdef GDK_WINDOWING_X11 +#include <gdk/gdkx.h> +#include <X11/XKBlib.h> +#include <stdbool.h> +#include <string.h> + +/* Xorg Linux + kbd (offset + mangled XT keycodes) */ +#include "vncdisplaykeymap_xorgkbd2xtkbd.c" +/* Xorg OS-X aka XQuartz (offset OS-X keycodes) */ +#include "vncdisplaykeymap_xorgxquartz2xtkbd.c" +/* Xorg Cygwin aka XWin (offset + mangled XT keycodes) */ +#include "vncdisplaykeymap_xorgxwin2xtkbd.c" + +/* Gtk2 compat */ +#ifndef GDK_IS_X11_WINDOW +#define GDK_IS_X11_WINDOW(win) (1) +#endif +#endif + +#ifdef GDK_WINDOWING_WIN32 +/* Win32 native virtual keycodes */ +#include "vncdisplaykeymap_win322xtkbd.c" + +/* Gtk2 compat */ +#ifndef GDK_IS_WIN32_WINDOW +#define GDK_IS_WIN32_WINDOW(win) (1) +#endif +#endif + +#ifdef GDK_WINDOWING_QUARTZ +/* OS-X native keycodes */ +#include "vncdisplaykeymap_osx2xtkbd.c" + +/* Gtk2 compat */ +#ifndef GDK_IS_QUARTZ_WINDOW +#define GDK_IS_QUARTZ_WINDOW(win) (1) +#endif +#endif + +#ifdef GDK_WINDOWING_BROADWAY +/* X11 keysyms */ +#include "vncdisplaykeymap_x112xtkbd.c" + +/* Gtk2 compat */ +#ifndef GDK_IS_BROADWAY_WINDOW +#define GDK_IS_BROADWAY_WINDOW(win) (1) +#endif + +#endif + +#ifdef GDK_WINDOWING_X11 + +#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0) + +static gboolean check_for_xwin(GdkDisplay *dpy) +{ + char *vendor = ServerVendor(gdk_x11_display_get_xdisplay(dpy)); + + if (strstr(vendor, "Cygwin/X")) + return TRUE; + + return FALSE; +} + +static gboolean check_for_xquartz(GdkDisplay *dpy) +{ + int nextensions; + int i; + gboolean match = FALSE; + char **extensions = XListExtensions(gdk_x11_display_get_xdisplay(dpy), + &nextensions); + for (i = 0 ; extensions != NULL && i < nextensions ; i++) { + if (strcmp(extensions[i], "Apple-WM") == 0 || + strcmp(extensions[i], "Apple-DRI") == 0) + match = TRUE; + } + if (extensions) + XFreeExtensionList(extensions); + + return match; +} +#endif + +const guint16 *vnc_display_keymap_gdk2xtkbd_table(GdkWindow *window, + size_t *maplen) +{ +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_WINDOW(window)) { + XkbDescPtr desc; + const gchar *keycodes = NULL; + GdkDisplay *dpy = gdk_window_get_display(window); + + /* There is no easy way to determine what X11 server + * and platform & keyboard driver is in use. Thus we + * do best guess heuristics. + * + * This will need more work for people with other + * X servers..... patches welcomed. + */ + + Display *xdisplay = gdk_x11_display_get_xdisplay(dpy); + desc = XkbGetMap(xdisplay, + XkbGBN_AllComponentsMask, + XkbUseCoreKbd); + if (desc) { + if (XkbGetNames(xdisplay, XkbKeycodesNameMask, desc) == Success) { + keycodes = gdk_x11_get_xatom_name(desc->names->keycodes); + if (!keycodes) + g_warning("could not lookup keycode name"); + } + XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); + } + + if (check_for_xwin(dpy)) { + VNC_DEBUG("Using xwin keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_xorgxwin2xtkbd); + return keymap_xorgxwin2xtkbd; + } else if (check_for_xquartz(dpy)) { + VNC_DEBUG("Using xquartz keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_xorgxquartz2xtkbd); + return keymap_xorgxquartz2xtkbd; + } else if (keycodes && STRPREFIX(keycodes, "evdev")) { + VNC_DEBUG("Using evdev keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_xorgevdev2xtkbd); + return keymap_xorgevdev2xtkbd; + } else if (keycodes && STRPREFIX(keycodes, "xfree86")) { + VNC_DEBUG("Using xfree86 keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_xorgkbd2xtkbd); + return keymap_xorgkbd2xtkbd; + } else { + g_warning("Unknown keycode mapping '%s'.\n" + "Please report to gtk-vnc-list@gnome.org\n" + "including the following information:\n" + "\n" + " - Operating system\n" + " - GDK build\n" + " - X11 Server\n" + " - xprop -root\n" + " - xdpyinfo\n", + keycodes); + return NULL; + } + } +#endif + +#ifdef GDK_WINDOWING_WIN32 + if (GDK_IS_WIN32_WINDOW(window)) { + VNC_DEBUG("Using Win32 virtual keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_win322xtkbd); + return keymap_win322xtkbd; + } +#endif + +#ifdef GDK_WINDOWING_QUARTZ + if (GDK_IS_QUARTZ_WINDOW(window)) { + VNC_DEBUG("Using OS-X virtual keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_osx2xtkbd); + return keymap_osx2xtkbd; + } +#endif + +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_WINDOW(window)) { + VNC_DEBUG("Using Wayland Xorg/evdev virtual keycode mapping"); + *maplen = G_N_ELEMENTS(keymap_xorgevdev2xtkbd); + return keymap_xorgevdev2xtkbd; + } +#endif + +#ifdef GDK_WINDOWING_BROADWAY + if (GDK_IS_BROADWAY_WINDOW(window)) { + g_warning("experimental: using broadway, x11 virtual keysym mapping - with very limited support. See also https://bugzilla.gnome.org/show_bug.cgi?id=700105"); + + *maplen = G_N_ELEMENTS(keymap_x112xtkbd); + return keymap_x112xtkbd; + } +#endif + + g_warning("Unsupported GDK Windowing platform.\n" + "Disabling extended keycode tables.\n" + "Please report to gtk-vnc-list@gnome.org\n" + "including the following information:\n" + "\n" + " - Operating system\n" + " - GDK Windowing system build\n"); + return NULL; +} + +guint16 vnc_display_keymap_gdk2xtkbd(const guint16 *keycode_map, + size_t keycode_maplen, + guint16 keycode) +{ + if (!keycode_map) + return 0; + if (keycode >= keycode_maplen) + return 0; + return keycode_map[keycode]; +} + +/* Set the keymap entries */ +void vnc_display_keyval_set_entries(void) +{ + size_t i; + if (ref_count_for_untranslated_keys == 0) + for (i = 0; i < sizeof(untranslated_keys) / sizeof(untranslated_keys[0]); i++) + gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), + untranslated_keys[i].keyval, + &untranslated_keys[i].keys, + &untranslated_keys[i].n_keys); + ref_count_for_untranslated_keys++; +} + +/* Free the keymap entries */ +void vnc_display_keyval_free_entries(void) +{ + size_t i; + + if (ref_count_for_untranslated_keys == 0) + return; + + ref_count_for_untranslated_keys--; + if (ref_count_for_untranslated_keys == 0) + for (i = 0; i < sizeof(untranslated_keys) / sizeof(untranslated_keys[0]); i++) + g_free(untranslated_keys[i].keys); + +} + +/* Get the keyval from the keycode without the level. */ +guint vnc_display_keyval_from_keycode(guint keycode, guint keyval) +{ + size_t i; + for (i = 0; i < sizeof(untranslated_keys) / sizeof(untranslated_keys[0]); i++) { + if (keycode == untranslated_keys[i].keys[0].keycode) { + return untranslated_keys[i].keyval; + } + } + + return keyval; +} +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/src/vncdisplaykeymap.h b/src/vncdisplaykeymap.h new file mode 100644 index 0000000..3ec55d5 --- /dev/null +++ b/src/vncdisplaykeymap.h @@ -0,0 +1,36 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> + * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com> + * + * 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.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef VNC_DISPLAY_KEYMAP_H +#define VNC_DISPLAY_KEYMAP_H + +#include <glib.h> + +const guint16 *vnc_display_keymap_gdk2xtkbd_table(GdkWindow *window, + size_t *maplen); +guint16 vnc_display_keymap_gdk2xtkbd(const guint16 *keycode_map, + size_t keycode_maplen, + guint16 keycode); +void vnc_display_keyval_set_entries(void); +void vnc_display_keyval_free_entries(void); +guint vnc_display_keyval_from_keycode(guint keycode, guint keyval); + +#endif /* VNC_DISPLAY_KEYMAP_H */ diff --git a/src/vncdisplaykeymap_osx2xtkbd.c b/src/vncdisplaykeymap_osx2xtkbd.c new file mode 100644 index 0000000..3c61294 --- /dev/null +++ b/src/vncdisplaykeymap_osx2xtkbd.c @@ -0,0 +1,117 @@ +static const guint16 keymap_osx2xtkbd[] = { + [0x0] = 0x1e, /* 0 (ANSI_A) => 30 via 30 (KEY_A) */ + [0x1] = 0x1f, /* 1 (ANSI_S) => 31 via 31 (KEY_S) */ + [0x2] = 0x20, /* 2 (ANSI_D) => 32 via 32 (KEY_D) */ + [0x3] = 0x21, /* 3 (ANSI_F) => 33 via 33 (KEY_F) */ + [0x4] = 0x23, /* 4 (ANSI_H) => 35 via 35 (KEY_H) */ + [0x5] = 0x22, /* 5 (ANSI_G) => 34 via 34 (KEY_G) */ + [0x6] = 0x2c, /* 6 (ANSI_Z) => 44 via 44 (KEY_Z) */ + [0x7] = 0x2d, /* 7 (ANSI_X) => 45 via 45 (KEY_X) */ + [0x8] = 0x2e, /* 8 (ANSI_C) => 46 via 46 (KEY_C) */ + [0x9] = 0x2f, /* 9 (ANSI_V) => 47 via 47 (KEY_V) */ + [0xa] = 0x70, /* 10 (ISO_Section) => 112 via 170 (KEY_ISO) */ + [0xb] = 0x30, /* 11 (ANSI_B) => 48 via 48 (KEY_B) */ + [0xc] = 0x10, /* 12 (ANSI_Q) => 16 via 16 (KEY_Q) */ + [0xd] = 0x11, /* 13 (ANSI_W) => 17 via 17 (KEY_W) */ + [0xe] = 0x12, /* 14 (ANSI_E) => 18 via 18 (KEY_E) */ + [0xf] = 0x13, /* 15 (ANSI_R) => 19 via 19 (KEY_R) */ + [0x10] = 0x15, /* 16 (ANSI_Y) => 21 via 21 (KEY_Y) */ + [0x11] = 0x14, /* 17 (ANSI_T) => 20 via 20 (KEY_T) */ + [0x12] = 0x2, /* 18 (ANSI_1) => 2 via 2 (KEY_1) */ + [0x13] = 0x3, /* 19 (ANSI_2) => 3 via 3 (KEY_2) */ + [0x14] = 0x4, /* 20 (ANSI_3) => 4 via 4 (KEY_3) */ + [0x15] = 0x5, /* 21 (ANSI_4) => 5 via 5 (KEY_4) */ + [0x16] = 0x7, /* 22 (ANSI_6) => 7 via 7 (KEY_6) */ + [0x17] = 0x6, /* 23 (ANSI_5) => 6 via 6 (KEY_5) */ + [0x18] = 0xd, /* 24 (ANSI_Equal) => 13 via 13 (KEY_EQUAL) */ + [0x19] = 0xa, /* 25 (ANSI_9) => 10 via 10 (KEY_9) */ + [0x1a] = 0x8, /* 26 (ANSI_7) => 8 via 8 (KEY_7) */ + [0x1b] = 0xc, /* 27 (ANSI_Minus) => 12 via 12 (KEY_MINUS) */ + [0x1c] = 0x9, /* 28 (ANSI_8) => 9 via 9 (KEY_8) */ + [0x1d] = 0xb, /* 29 (ANSI_0) => 11 via 11 (KEY_0) */ + [0x1e] = 0x1b, /* 30 (ANSI_RightBracket) => 27 via 27 (KEY_RIGHTBRACE) */ + [0x1f] = 0x18, /* 31 (ANSI_O) => 24 via 24 (KEY_O) */ + [0x20] = 0x16, /* 32 (ANSI_U) => 22 via 22 (KEY_U) */ + [0x21] = 0x1a, /* 33 (ANSI_LeftBracket) => 26 via 26 (KEY_LEFTBRACE) */ + [0x22] = 0x17, /* 34 (ANSI_I) => 23 via 23 (KEY_I) */ + [0x23] = 0x19, /* 35 (ANSI_P) => 25 via 25 (KEY_P) */ + [0x24] = 0x1c, /* 36 (Return) => 28 via 28 (KEY_ENTER) */ + [0x25] = 0x26, /* 37 (ANSI_L) => 38 via 38 (KEY_L) */ + [0x26] = 0x24, /* 38 (ANSI_J) => 36 via 36 (KEY_J) */ + [0x27] = 0x28, /* 39 (ANSI_Quote) => 40 via 40 (KEY_APOSTROPHE) */ + [0x28] = 0x25, /* 40 (ANSI_K) => 37 via 37 (KEY_K) */ + [0x29] = 0x27, /* 41 (ANSI_Semicolon) => 39 via 39 (KEY_SEMICOLON) */ + [0x2a] = 0x2b, /* 42 (ANSI_Backslash) => 43 via 43 (KEY_BACKSLASH) */ + [0x2b] = 0x33, /* 43 (ANSI_Comma) => 51 via 51 (KEY_COMMA) */ + [0x2c] = 0x35, /* 44 (ANSI_Slash) => 53 via 53 (KEY_SLASH) */ + [0x2d] = 0x31, /* 45 (ANSI_N) => 49 via 49 (KEY_N) */ + [0x2e] = 0x32, /* 46 (ANSI_M) => 50 via 50 (KEY_M) */ + [0x2f] = 0x34, /* 47 (ANSI_Period) => 52 via 52 (KEY_DOT) */ + [0x30] = 0xf, /* 48 (Tab) => 15 via 15 (KEY_TAB) */ + [0x31] = 0x39, /* 49 (Space) => 57 via 57 (KEY_SPACE) */ + [0x32] = 0x29, /* 50 (ANSI_Grave) => 41 via 41 (KEY_GRAVE) */ + [0x33] = 0xe, /* 51 (Delete) => 14 via 14 (KEY_BACKSPACE) */ + [0x35] = 0x1, /* 53 (Escape) => 1 via 1 (KEY_ESC) */ + [0x37] = 0x15b, /* 55 (Command) => 347 via 125 (KEY_LEFTMETA) */ + [0x38] = 0x2a, /* 56 (Shift) => 42 via 42 (KEY_LEFTSHIFT) */ + [0x39] = 0x3a, /* 57 (CapsLock) => 58 via 58 (KEY_CAPSLOCK) */ + [0x3a] = 0x38, /* 58 (Option) => 56 via 56 (KEY_LEFTALT) */ + [0x3b] = 0x1d, /* 59 (Control) => 29 via 29 (KEY_LEFTCTRL) */ + [0x3c] = 0x36, /* 60 (RightShift) => 54 via 54 (KEY_RIGHTSHIFT) */ + [0x3d] = 0x138, /* 61 (RightOption) => 312 via 100 (KEY_RIGHTALT) */ + [0x3e] = 0x11d, /* 62 (RightControl) => 285 via 97 (KEY_RIGHTCTRL) */ + [0x3f] = 0x15d, /* 63 (Function) => 349 via 127 (KEY_COMPOSE) */ + [0x40] = 0x103, /* 64 (F17) => 259 via 187 (KEY_F17) */ + [0x41] = 0x53, /* 65 (ANSI_KeypadDecimal) => 83 via 83 (KEY_KPDOT) */ + [0x43] = 0x37, /* 67 (ANSI_KeypadMultiply) => 55 via 55 (KEY_KPASTERISK) */ + [0x45] = 0x4e, /* 69 (ANSI_KeypadPlus) => 78 via 78 (KEY_KPPLUS) */ + [0x47] = 0x7e, /* 71 (ANSI_KeypadClear????) => 126 via 121 (KEY_KPCOMMA) */ + [0x48] = 0x130, /* 72 (VolumeUp) => 304 via 115 (KEY_VOLUMEUP) */ + [0x49] = 0x12e, /* 73 (VolumeDown) => 302 via 114 (KEY_VOLUMEDOWN) */ + [0x4a] = 0x120, /* 74 (Mute) => 288 via 113 (KEY_MUTE) */ + [0x4b] = 0x135, /* 75 (ANSI_KeypadDivide) => 309 via 98 (KEY_KPSLASH) */ + [0x4c] = 0x11c, /* 76 (ANSI_KeypadEnter) => 284 via 96 (KEY_KPENTER) */ + [0x4e] = 0x4a, /* 78 (ANSI_KeypadMinus) => 74 via 74 (KEY_KPMINUS) */ + [0x4f] = 0x177, /* 79 (F18) => 375 via 188 (KEY_F18) */ + [0x50] = 0x104, /* 80 (F19) => 260 via 189 (KEY_F19) */ + [0x51] = 0x59, /* 81 (ANSI_KeypadEquals) => 89 via 117 (KEY_KPEQUAL) */ + [0x52] = 0x52, /* 82 (ANSI_Keypad0) => 82 via 82 (KEY_KP0) */ + [0x53] = 0x4f, /* 83 (ANSI_Keypad1) => 79 via 79 (KEY_KP1) */ + [0x54] = 0x50, /* 84 (ANSI_Keypad2) => 80 via 80 (KEY_KP2) */ + [0x55] = 0x51, /* 85 (ANSI_Keypad3) => 81 via 81 (KEY_KP3) */ + [0x56] = 0x4b, /* 86 (ANSI_Keypad4) => 75 via 75 (KEY_KP4) */ + [0x57] = 0x4c, /* 87 (ANSI_Keypad5) => 76 via 76 (KEY_KP5) */ + [0x58] = 0x4d, /* 88 (ANSI_Keypad6) => 77 via 77 (KEY_KP6) */ + [0x59] = 0x47, /* 89 (ANSI_Keypad7) => 71 via 71 (KEY_KP7) */ + [0x5a] = 0x5a, /* 90 (F20) => 90 via 190 (KEY_F20) */ + [0x5b] = 0x48, /* 91 (ANSI_Keypad8) => 72 via 72 (KEY_KP8) */ + [0x5c] = 0x49, /* 92 (ANSI_Keypad9) => 73 via 73 (KEY_KP9) */ + [0x5d] = 0x7d, /* 93 (JIS_Yen) => 125 via 124 (KEY_YEN) */ + [0x5f] = 0x5c, /* 95 (JIS_KeypadComma) => 92 via 95 (KEY_KPJPCOMMA) */ + [0x60] = 0x3f, /* 96 (F5) => 63 via 63 (KEY_F5) */ + [0x61] = 0x40, /* 97 (F6) => 64 via 64 (KEY_F6) */ + [0x62] = 0x41, /* 98 (F7) => 65 via 65 (KEY_F7) */ + [0x63] = 0x3d, /* 99 (F3) => 61 via 61 (KEY_F3) */ + [0x64] = 0x42, /* 100 (F8) => 66 via 66 (KEY_F8) */ + [0x65] = 0x43, /* 101 (F9) => 67 via 67 (KEY_F9) */ + [0x67] = 0x57, /* 103 (F11) => 87 via 87 (KEY_F11) */ + [0x68] = 0x78, /* 104 (JIS_Kana????) => 120 via 90 (KEY_KATAKANA) */ + [0x69] = 0x5d, /* 105 (F13) => 93 via 183 (KEY_F13) */ + [0x6a] = 0x55, /* 106 (F16) => 85 via 186 (KEY_F16) */ + [0x6b] = 0x5e, /* 107 (F14) => 94 via 184 (KEY_F14) */ + [0x6d] = 0x44, /* 109 (F10) => 68 via 68 (KEY_F10) */ + [0x6f] = 0x58, /* 111 (F12) => 88 via 88 (KEY_F12) */ + [0x71] = 0x5f, /* 113 (F15) => 95 via 185 (KEY_F15) */ + [0x73] = 0x147, /* 115 (Home) => 327 via 102 (KEY_HOME) */ + [0x74] = 0x149, /* 116 (PageUp) => 329 via 104 (KEY_PAGEUP) */ + [0x75] = 0x153, /* 117 (ForwardDelete) => 339 via 111 (KEY_DELETE) */ + [0x76] = 0x3e, /* 118 (F4) => 62 via 62 (KEY_F4) */ + [0x77] = 0x14f, /* 119 (End) => 335 via 107 (KEY_END) */ + [0x78] = 0x3c, /* 120 (F2) => 60 via 60 (KEY_F2) */ + [0x79] = 0x151, /* 121 (PageDown) => 337 via 109 (KEY_PAGEDOWN) */ + [0x7a] = 0x3b, /* 122 (F1) => 59 via 59 (KEY_F1) */ + [0x7b] = 0x14b, /* 123 (LeftArrow) => 331 via 105 (KEY_LEFT) */ + [0x7c] = 0x14d, /* 124 (RightArrow) => 333 via 106 (KEY_RIGHT) */ + [0x7d] = 0x150, /* 125 (DownArrow) => 336 via 108 (KEY_DOWN) */ + [0x7e] = 0x148, /* 126 (UpArrow) => 328 via 103 (KEY_UP) */ +}; diff --git a/src/vncdisplaykeymap_win322xtkbd.c b/src/vncdisplaykeymap_win322xtkbd.c new file mode 100644 index 0000000..40aab9e --- /dev/null +++ b/src/vncdisplaykeymap_win322xtkbd.c @@ -0,0 +1,141 @@ +static const guint16 keymap_win322xtkbd[] = { + [0x8] = 0xe, /* 8 (VK_BACK) => 14 via 14 (KEY_BACKSPACE) */ + [0x9] = 0xf, /* 9 (VK_TAB) => 15 via 15 (KEY_TAB) */ + [0xd] = 0x1c, /* 13 (VK_RETURN) => 28 via 28 (KEY_ENTER) */ + [0x10] = 0x2a, /* 16 (VK_LSHIFT) => 42 via 42 (KEY_LEFTSHIFT) */ + [0x11] = 0x1d, /* 17 (VK_CONTROL) => 29 via 29 (KEY_LEFTCTRL) */ + [0x12] = 0x38, /* 18 (VK_MENU) => 56 via 56 (KEY_LEFTALT) */ + [0x13] = 0x146, /* 19 (VK_PAUSE) => 326 via 119 (KEY_PAUSE) */ + [0x14] = 0x3a, /* 20 (VK_CAPITAL) => 58 via 58 (KEY_CAPSLOCK) */ + [0x19] = 0x10d, /* 25 (VK_HANJA) => 269 via 123 (KEY_HANJA) */ + [0x1b] = 0x1, /* 27 (VK_ESCAPE) => 1 via 1 (KEY_ESC) */ + [0x20] = 0x39, /* 32 (VK_SPACE) => 57 via 57 (KEY_SPACE) */ + [0x21] = 0x149, /* 33 (VK_PRIOR) => 329 via 104 (KEY_PAGEUP) */ + [0x22] = 0x151, /* 34 (VK_NEXT) => 337 via 109 (KEY_PAGEDOWN) */ + [0x23] = 0x14f, /* 35 (VK_END) => 335 via 107 (KEY_END) */ + [0x24] = 0x147, /* 36 (VK_HOME) => 327 via 102 (KEY_HOME) */ + [0x25] = 0x14b, /* 37 (VK_LEFT) => 331 via 105 (KEY_LEFT) */ + [0x26] = 0x148, /* 38 (VK_UP) => 328 via 103 (KEY_UP) */ + [0x27] = 0x14d, /* 39 (VK_RIGHT) => 333 via 106 (KEY_RIGHT) */ + [0x28] = 0x150, /* 40 (VK_DOWN) => 336 via 108 (KEY_DOWN) */ + [0x2a] = 0x139, /* 42 (VK_PRINT) => 313 via 210 (KEY_PRINT) */ + [0x2c] = 0x54, /* 44 (VK_SNAPSHOT ???) => 84 via 99 (KEY_SYSRQ) */ + [0x2d] = 0x152, /* 45 (VK_INSERT) => 338 via 110 (KEY_INSERT) */ + [0x2e] = 0x153, /* 46 (VK_DELETE) => 339 via 111 (KEY_DELETE) */ + [0x2f] = 0x175, /* 47 (VK_HELP) => 373 via 138 (KEY_HELP) */ + [0x30] = 0xb, /* 48 (VK_0) => 11 via 11 (KEY_0) */ + [0x31] = 0x2, /* 49 (VK_1) => 2 via 2 (KEY_1) */ + [0x32] = 0x3, /* 50 (VK_2) => 3 via 3 (KEY_2) */ + [0x33] = 0x4, /* 51 (VK_3) => 4 via 4 (KEY_3) */ + [0x34] = 0x5, /* 52 (VK_4) => 5 via 5 (KEY_4) */ + [0x35] = 0x6, /* 53 (VK_5) => 6 via 6 (KEY_5) */ + [0x36] = 0x7, /* 54 (VK_6) => 7 via 7 (KEY_6) */ + [0x37] = 0x8, /* 55 (VK_7) => 8 via 8 (KEY_7) */ + [0x38] = 0x9, /* 56 (VK_8) => 9 via 9 (KEY_8) */ + [0x39] = 0xa, /* 57 (VK_9) => 10 via 10 (KEY_9) */ + [0x41] = 0x1e, /* 65 (VK_A) => 30 via 30 (KEY_A) */ + [0x42] = 0x30, /* 66 (VK_B) => 48 via 48 (KEY_B) */ + [0x43] = 0x2e, /* 67 (VK_C) => 46 via 46 (KEY_C) */ + [0x44] = 0x20, /* 68 (VK_D) => 32 via 32 (KEY_D) */ + [0x45] = 0x12, /* 69 (VK_E) => 18 via 18 (KEY_E) */ + [0x46] = 0x21, /* 70 (VK_F) => 33 via 33 (KEY_F) */ + [0x47] = 0x22, /* 71 (VK_G) => 34 via 34 (KEY_G) */ + [0x48] = 0x23, /* 72 (VK_H) => 35 via 35 (KEY_H) */ + [0x49] = 0x17, /* 73 (VK_I) => 23 via 23 (KEY_I) */ + [0x4a] = 0x24, /* 74 (VK_J) => 36 via 36 (KEY_J) */ + [0x4b] = 0x25, /* 75 (VK_K) => 37 via 37 (KEY_K) */ + [0x4c] = 0x26, /* 76 (VK_L) => 38 via 38 (KEY_L) */ + [0x4d] = 0x32, /* 77 (VK_M) => 50 via 50 (KEY_M) */ + [0x4e] = 0x31, /* 78 (VK_N) => 49 via 49 (KEY_N) */ + [0x4f] = 0x18, /* 79 (VK_O) => 24 via 24 (KEY_O) */ + [0x50] = 0x19, /* 80 (VK_P) => 25 via 25 (KEY_P) */ + [0x51] = 0x10, /* 81 (VK_Q) => 16 via 16 (KEY_Q) */ + [0x52] = 0x13, /* 82 (VK_R) => 19 via 19 (KEY_R) */ + [0x53] = 0x1f, /* 83 (VK_S) => 31 via 31 (KEY_S) */ + [0x54] = 0x14, /* 84 (VK_T) => 20 via 20 (KEY_T) */ + [0x55] = 0x16, /* 85 (VK_U) => 22 via 22 (KEY_U) */ + [0x56] = 0x2f, /* 86 (VK_V) => 47 via 47 (KEY_V) */ + [0x57] = 0x11, /* 87 (VK_W) => 17 via 17 (KEY_W) */ + [0x58] = 0x2d, /* 88 (VK_X) => 45 via 45 (KEY_X) */ + [0x59] = 0x15, /* 89 (VK_Y) => 21 via 21 (KEY_Y) */ + [0x5a] = 0x2c, /* 90 (VK_Z) => 44 via 44 (KEY_Z) */ + [0x5b] = 0x15b, /* 91 (VK_LWIN) => 347 via 125 (KEY_LEFTMETA) */ + [0x5c] = 0x15c, /* 92 (VK_RWIN) => 348 via 126 (KEY_RIGHTMETA) */ + [0x5d] = 0x15d, /* 93 (VK_APPS) => 349 via 127 (KEY_COMPOSE) */ + [0x5f] = 0x15f, /* 95 (VK_SLEEP) => 351 via 142 (KEY_SLEEP) */ + [0x60] = 0x52, /* 96 (VK_NUMPAD0) => 82 via 82 (KEY_KP0) */ + [0x61] = 0x4f, /* 97 (VK_NUMPAD1) => 79 via 79 (KEY_KP1) */ + [0x62] = 0x50, /* 98 (VK_NUMPAD2) => 80 via 80 (KEY_KP2) */ + [0x63] = 0x51, /* 99 (VK_NUMPAD3) => 81 via 81 (KEY_KP3) */ + [0x64] = 0x4b, /* 100 (VK_NUMPAD4) => 75 via 75 (KEY_KP4) */ + [0x65] = 0x4c, /* 101 (VK_NUMPAD5) => 76 via 76 (KEY_KP5) */ + [0x66] = 0x4d, /* 102 (VK_NUMPAD6) => 77 via 77 (KEY_KP6) */ + [0x67] = 0x47, /* 103 (VK_NUMPAD7) => 71 via 71 (KEY_KP7) */ + [0x68] = 0x48, /* 104 (VK_NUMPAD8) => 72 via 72 (KEY_KP8) */ + [0x69] = 0x49, /* 105 (VK_NUMPAD9) => 73 via 73 (KEY_KP9) */ + [0x6a] = 0x37, /* 106 (VK_MULTIPLY) => 55 via 55 (KEY_KPASTERISK) */ + [0x6b] = 0x4e, /* 107 (VK_ADD) => 78 via 78 (KEY_KPPLUS) */ + [0x6c] = 0x7e, /* 108 (VK_SEPARATOR??) => 126 via 121 (KEY_KPCOMMA) */ + [0x6d] = 0x4a, /* 109 (VK_SUBTRACT) => 74 via 74 (KEY_KPMINUS) */ + [0x6e] = 0x53, /* 110 (VK_DECIMAL) => 83 via 83 (KEY_KPDOT) */ + [0x6f] = 0x135, /* 111 (VK_DIVIDE) => 309 via 98 (KEY_KPSLASH) */ + [0x70] = 0x3b, /* 112 (VK_F1) => 59 via 59 (KEY_F1) */ + [0x71] = 0x3c, /* 113 (VK_F2) => 60 via 60 (KEY_F2) */ + [0x72] = 0x3d, /* 114 (VK_F3) => 61 via 61 (KEY_F3) */ + [0x73] = 0x3e, /* 115 (VK_F4) => 62 via 62 (KEY_F4) */ + [0x74] = 0x3f, /* 116 (VK_F5) => 63 via 63 (KEY_F5) */ + [0x75] = 0x40, /* 117 (VK_F6) => 64 via 64 (KEY_F6) */ + [0x76] = 0x41, /* 118 (VK_F7) => 65 via 65 (KEY_F7) */ + [0x77] = 0x42, /* 119 (VK_F8) => 66 via 66 (KEY_F8) */ + [0x78] = 0x43, /* 120 (VK_F9) => 67 via 67 (KEY_F9) */ + [0x79] = 0x44, /* 121 (VK_F10) => 68 via 68 (KEY_F10) */ + [0x7a] = 0x57, /* 122 (VK_F11) => 87 via 87 (KEY_F11) */ + [0x7b] = 0x58, /* 123 (VK_F12) => 88 via 88 (KEY_F12) */ + [0x7c] = 0x5d, /* 124 (VK_F13) => 93 via 183 (KEY_F13) */ + [0x7d] = 0x5e, /* 125 (VK_F14) => 94 via 184 (KEY_F14) */ + [0x7e] = 0x5f, /* 126 (VK_F15) => 95 via 185 (KEY_F15) */ + [0x7f] = 0x55, /* 127 (VK_F16) => 85 via 186 (KEY_F16) */ + [0x80] = 0x103, /* 128 (VK_F17) => 259 via 187 (KEY_F17) */ + [0x81] = 0x177, /* 129 (VK_F18) => 375 via 188 (KEY_F18) */ + [0x82] = 0x104, /* 130 (VK_F19) => 260 via 189 (KEY_F19) */ + [0x83] = 0x5a, /* 131 (VK_F20) => 90 via 190 (KEY_F20) */ + [0x84] = 0x74, /* 132 (VK_F21) => 116 via 191 (KEY_F21) */ + [0x85] = 0x179, /* 133 (VK_F22) => 377 via 192 (KEY_F22) */ + [0x86] = 0x6d, /* 134 (VK_F23) => 109 via 193 (KEY_F23) */ + [0x87] = 0x6f, /* 135 (VK_F24) => 111 via 194 (KEY_F24) */ + [0x90] = 0x45, /* 144 (VK_NUMLOCK) => 69 via 69 (KEY_NUMLOCK) */ + [0x91] = 0x46, /* 145 (VK_SCROLL) => 70 via 70 (KEY_SCROLLLOCK) */ + [0xa0] = 0x2a, /* 160 (VK_LSHIFT) => 42 via 42 (KEY_LEFTSHIFT) */ + [0xa1] = 0x36, /* 161 (VK_RSHIFT) => 54 via 54 (KEY_RIGHTSHIFT) */ + [0xa2] = 0x1d, /* 162 (VK_CONTROL) => 29 via 29 (KEY_LEFTCTRL) */ + [0xa3] = 0x11d, /* 163 (VK_RCONTROL) => 285 via 97 (KEY_RIGHTCTRL) */ + [0xa4] = 0x38, /* 164 (VK_MENU) => 56 via 56 (KEY_LEFTALT) */ + [0xa5] = 0x138, /* 165 (VK_RMENU) => 312 via 100 (KEY_RIGHTALT) */ + [0xa6] = 0x16a, /* 166 (VK_BROWSER_BACK) => 362 via 158 (KEY_BACK) */ + [0xa7] = 0x169, /* 167 (VK_BROWSER_FORWARD) => 361 via 159 (KEY_FORWARD) */ + [0xa8] = 0x167, /* 168 (VK_BROWSER_REFRESH) => 359 via 173 (KEY_REFRESH) */ + [0xa9] = 0x168, /* 169 (VK_BROWSER_STOP) => 360 via 128 (KEY_STOP) */ + [0xaa] = 0x165, /* 170 (VK_BROWSER_SEARCH) => 357 via 217 (KEY_SEARCH) */ + [0xac] = 0x132, /* 172 (VK_BROWSER_HOME) => 306 via 172 (KEY_HOMEPAGE) */ + [0xad] = 0x120, /* 173 (VK_VOLUME_MUTE) => 288 via 113 (KEY_MUTE) */ + [0xae] = 0x12e, /* 174 (VK_VOLUME_DOWN) => 302 via 114 (KEY_VOLUMEDOWN) */ + [0xaf] = 0x130, /* 175 (VK_VOLUME_UP) => 304 via 115 (KEY_VOLUMEUP) */ + [0xb0] = 0x119, /* 176 (VK_MEDIA_NEXT_TRACK) => 281 via 163 (KEY_NEXTSONG) */ + [0xb1] = 0x110, /* 177 (VK_MEDIA_PREV_TRACK) => 272 via 165 (KEY_PREVIOUSSONG) */ + [0xb2] = 0x124, /* 178 (VK_MEDIA_STOP) => 292 via 166 (KEY_STOPCD) */ + [0xb3] = 0x122, /* 179 (VK_MEDIA_PLAY_PAUSE) => 290 via 164 (KEY_PLAYPAUSE) */ + [0xb4] = 0x13f, /* 180 (VK_LAUNCH_MAIL) => 319 via 215 (KEY_EMAIL) */ + [0xba] = 0x27, /* 186 (VK_OEM_1) => 39 via 39 (KEY_SEMICOLON) */ + [0xbb] = 0xd, /* 187 (VK_OEM_PLUS) => 13 via 13 (KEY_EQUAL) */ + [0xbc] = 0x33, /* 188 (VK_OEM_COMMA) => 51 via 51 (KEY_COMMA) */ + [0xbd] = 0xc, /* 189 (VK_OEM_MINUS) => 12 via 12 (KEY_MINUS) */ + [0xbe] = 0x34, /* 190 (VK_OEM_PERIOD) => 52 via 52 (KEY_DOT) */ + [0xbf] = 0x35, /* 191 (VK_OEM_2) => 53 via 53 (KEY_SLASH) */ + [0xc0] = 0x29, /* 192 (VK_OEM_3) => 41 via 41 (KEY_GRAVE) */ + [0xdb] = 0x1a, /* 219 (VK_OEM_4) => 26 via 26 (KEY_LEFTBRACE) */ + [0xdc] = 0x2b, /* 220 (VK_OEM_5) => 43 via 43 (KEY_BACKSLASH) */ + [0xdd] = 0x1b, /* 221 (VK_OEM_6) => 27 via 27 (KEY_RIGHTBRACE) */ + [0xde] = 0x28, /* 222 (VK_OEM_7) => 40 via 40 (KEY_APOSTROPHE) */ + [0xe1] = 0x56, /* 225 (VK_OEM_102) => 86 via 86 (KEY_102ND) */ + [0xfa] = 0x133, /* 250 (VK_PLAY) => 307 via 207 (KEY_PLAY) */ +}; diff --git a/src/vncdisplaykeymap_x112xtkbd.c b/src/vncdisplaykeymap_x112xtkbd.c new file mode 100644 index 0000000..b6b3c62 --- /dev/null +++ b/src/vncdisplaykeymap_x112xtkbd.c @@ -0,0 +1,132 @@ +static const guint16 keymap_x112xtkbd[] = { + [0x20] = 0x39, /* 32 (XK_space) => 57 via 57 (KEY_SPACE) */ + [0x27] = 0x28, /* 39 (XK_apostrophe) => 40 via 40 (KEY_APOSTROPHE) */ + [0x2c] = 0x33, /* 44 (XK_comma) => 51 via 51 (KEY_COMMA) */ + [0x2d] = 0xc, /* 45 (XK_minus) => 12 via 12 (KEY_MINUS) */ + [0x2e] = 0x34, /* 46 (XK_period) => 52 via 52 (KEY_DOT) */ + [0x2f] = 0x35, /* 47 (XK_slash) => 53 via 53 (KEY_SLASH) */ + [0x30] = 0xb, /* 48 (XK_0) => 11 via 11 (KEY_0) */ + [0x31] = 0x2, /* 49 (XK_1) => 2 via 2 (KEY_1) */ + [0x32] = 0x3, /* 50 (XK_2) => 3 via 3 (KEY_2) */ + [0x33] = 0x4, /* 51 (XK_3) => 4 via 4 (KEY_3) */ + [0x34] = 0x5, /* 52 (XK_4) => 5 via 5 (KEY_4) */ + [0x35] = 0x6, /* 53 (XK_5) => 6 via 6 (KEY_5) */ + [0x36] = 0x7, /* 54 (XK_6) => 7 via 7 (KEY_6) */ + [0x37] = 0x8, /* 55 (XK_7) => 8 via 8 (KEY_7) */ + [0x38] = 0x9, /* 56 (XK_8) => 9 via 9 (KEY_8) */ + [0x39] = 0xa, /* 57 (XK_9) => 10 via 10 (KEY_9) */ + [0x3b] = 0x27, /* 59 (XK_semicolon) => 39 via 39 (KEY_SEMICOLON) */ + [0x3d] = 0xd, /* 61 (XK_equal) => 13 via 13 (KEY_EQUAL) */ + [0x41] = 0x1e, /* 65 (XK_a) => 30 via 30 (KEY_A) */ + [0x42] = 0x30, /* 66 (XK_b) => 48 via 48 (KEY_B) */ + [0x43] = 0x2e, /* 67 (XK_c) => 46 via 46 (KEY_C) */ + [0x44] = 0x20, /* 68 (XK_d) => 32 via 32 (KEY_D) */ + [0x45] = 0x12, /* 69 (XK_e) => 18 via 18 (KEY_E) */ + [0x46] = 0x21, /* 70 (XK_f) => 33 via 33 (KEY_F) */ + [0x47] = 0x22, /* 71 (XK_g) => 34 via 34 (KEY_G) */ + [0x48] = 0x23, /* 72 (XK_h) => 35 via 35 (KEY_H) */ + [0x49] = 0x17, /* 73 (XK_i) => 23 via 23 (KEY_I) */ + [0x4a] = 0x24, /* 74 (XK_j) => 36 via 36 (KEY_J) */ + [0x4b] = 0x25, /* 75 (XK_K) => 37 via 37 (KEY_K) */ + [0x4c] = 0x26, /* 76 (XK_l) => 38 via 38 (KEY_L) */ + [0x4d] = 0x32, /* 77 (XK_m) => 50 via 50 (KEY_M) */ + [0x4e] = 0x31, /* 78 (XK_n) => 49 via 49 (KEY_N) */ + [0x4f] = 0x18, /* 79 (XK_o) => 24 via 24 (KEY_O) */ + [0x50] = 0x19, /* 80 (XK_p) => 25 via 25 (KEY_P) */ + [0x51] = 0x10, /* 81 (XK_q) => 16 via 16 (KEY_Q) */ + [0x52] = 0x13, /* 82 (XK_r) => 19 via 19 (KEY_R) */ + [0x53] = 0x1f, /* 83 (XK_s) => 31 via 31 (KEY_S) */ + [0x54] = 0x14, /* 84 (XK_t) => 20 via 20 (KEY_T) */ + [0x55] = 0x16, /* 85 (XK_u) => 22 via 22 (KEY_U) */ + [0x56] = 0x2f, /* 86 (XK_v) => 47 via 47 (KEY_V) */ + [0x57] = 0x11, /* 87 (XK_w) => 17 via 17 (KEY_W) */ + [0x58] = 0x2d, /* 88 (XK_x) => 45 via 45 (KEY_X) */ + [0x59] = 0x15, /* 89 (XK_y) => 21 via 21 (KEY_Y) */ + [0x5a] = 0x2c, /* 90 (XK_z) => 44 via 44 (KEY_Z) */ + [0x5b] = 0x1a, /* 91 (XK_bracketleft) => 26 via 26 (KEY_LEFTBRACE) */ + [0x5c] = 0x2b, /* 92 (XK_backslash) => 43 via 43 (KEY_BACKSLASH) */ + [0x5d] = 0x1b, /* 93 (XK_bracketright) => 27 via 27 (KEY_RIGHTBRACE) */ + [0x60] = 0x29, /* 96 (XK_grave) => 41 via 41 (KEY_GRAVE) */ + [0x61] = 0x1e, /* 97 (XK_a) => 30 via 30 (KEY_A) */ + [0x62] = 0x30, /* 98 (XK_b) => 48 via 48 (KEY_B) */ + [0x63] = 0x2e, /* 99 (XK_c) => 46 via 46 (KEY_C) */ + [0x64] = 0x20, /* 100 (XK_d) => 32 via 32 (KEY_D) */ + [0x65] = 0x12, /* 101 (XK_e) => 18 via 18 (KEY_E) */ + [0x66] = 0x21, /* 102 (XK_f) => 33 via 33 (KEY_F) */ + [0x67] = 0x22, /* 103 (XK_g) => 34 via 34 (KEY_G) */ + [0x68] = 0x23, /* 104 (XK_h) => 35 via 35 (KEY_H) */ + [0x69] = 0x17, /* 105 (XK_i) => 23 via 23 (KEY_I) */ + [0x6a] = 0x24, /* 106 (XK_j) => 36 via 36 (KEY_J) */ + [0x6b] = 0x25, /* 107 (XK_K) => 37 via 37 (KEY_K) */ + [0x6c] = 0x26, /* 108 (XK_l) => 38 via 38 (KEY_L) */ + [0x6d] = 0x32, /* 109 (XK_m) => 50 via 50 (KEY_M) */ + [0x6e] = 0x31, /* 110 (XK_n) => 49 via 49 (KEY_N) */ + [0x6f] = 0x18, /* 111 (XK_o) => 24 via 24 (KEY_O) */ + [0x70] = 0x19, /* 112 (XK_p) => 25 via 25 (KEY_P) */ + [0x71] = 0x10, /* 113 (XK_q) => 16 via 16 (KEY_Q) */ + [0x72] = 0x13, /* 114 (XK_r) => 19 via 19 (KEY_R) */ + [0x73] = 0x1f, /* 115 (XK_s) => 31 via 31 (KEY_S) */ + [0x74] = 0x14, /* 116 (XK_t) => 20 via 20 (KEY_T) */ + [0x75] = 0x16, /* 117 (XK_u) => 22 via 22 (KEY_U) */ + [0x76] = 0x2f, /* 118 (XK_v) => 47 via 47 (KEY_V) */ + [0x77] = 0x11, /* 119 (XK_w) => 17 via 17 (KEY_W) */ + [0x78] = 0x2d, /* 120 (XK_x) => 45 via 45 (KEY_X) */ + [0x79] = 0x15, /* 121 (XK_y) => 21 via 21 (KEY_Y) */ + [0x7a] = 0x2c, /* 122 (XK_z) => 44 via 44 (KEY_Z) */ + [0xd7] = 0x37, /* 215 (XK_multiply) => 55 via 55 (KEY_KPASTERISK) */ + [0xff08] = 0xe, /* 65288 (XK_BackSpace) => 14 via 14 (KEY_BACKSPACE) */ + [0xff09] = 0xf, /* 65289 (XK_Tab) => 15 via 15 (KEY_TAB) */ + [0xff0d] = 0x1c, /* 65293 (XK_Return) => 28 via 28 (KEY_ENTER) */ + [0xff13] = 0x146, /* 65299 (XK_Pause) => 326 via 119 (KEY_PAUSE) */ + [0xff14] = 0x46, /* 65300 (XK_Scroll_Lock) => 70 via 70 (KEY_SCROLLLOCK) */ + [0xff15] = 0x54, /* 65301 (XK_Sys_Req) => 84 via 99 (KEY_SYSRQ) */ + [0xff1b] = 0x1, /* 65307 (XK_Escape) => 1 via 1 (KEY_ESC) */ + [0xff50] = 0x147, /* 65360 (XK_Home) => 327 via 102 (KEY_HOME) */ + [0xff51] = 0x14b, /* 65361 (XK_Left) => 331 via 105 (KEY_LEFT) */ + [0xff52] = 0x148, /* 65362 (XK_Up) => 328 via 103 (KEY_UP) */ + [0xff53] = 0x14d, /* 65363 (XK_Right) => 333 via 106 (KEY_RIGHT) */ + [0xff54] = 0x150, /* 65364 (XK_Down) => 336 via 108 (KEY_DOWN) */ + [0xff55] = 0x149, /* 65365 (XK_Page_Up) => 329 via 104 (KEY_PAGEUP) */ + [0xff56] = 0x151, /* 65366 (XK_Page_Down) => 337 via 109 (KEY_PAGEDOWN) */ + [0xff57] = 0x14f, /* 65367 (XK_End) => 335 via 107 (KEY_END) */ + [0xff63] = 0x152, /* 65379 (XK_Insert) => 338 via 110 (KEY_INSERT) */ + [0xff6a] = 0x175, /* 65386 (XK_Help) => 373 via 138 (KEY_HELP) */ + [0xff7f] = 0x45, /* 65407 (XK_Num_Lock) => 69 via 69 (KEY_NUMLOCK) */ + [0xff8d] = 0x11c, /* 65421 (XK_KP_Enter) => 284 via 96 (KEY_KPENTER) */ + [0xffab] = 0x4e, /* 65451 (XK_KP_Add) => 78 via 78 (KEY_KPPLUS) */ + [0xffac] = 0x5c, /* 65452 (XK_KP_Separator) => 92 via 95 (KEY_KPJPCOMMA) */ + [0xffad] = 0x4a, /* 65453 (XK_KP_Subtract) => 74 via 74 (KEY_KPMINUS) */ + [0xffae] = 0x53, /* 65454 (XK_KP_Decimal) => 83 via 83 (KEY_KPDOT) */ + [0xffaf] = 0x135, /* 65455 (XK_KP_Divide) => 309 via 98 (KEY_KPSLASH) */ + [0xffb0] = 0x52, /* 65456 (XK_KP_0) => 82 via 82 (KEY_KP0) */ + [0xffb1] = 0x4f, /* 65457 (XK_KP_1) => 79 via 79 (KEY_KP1) */ + [0xffb2] = 0x50, /* 65458 (XK_KP_2) => 80 via 80 (KEY_KP2) */ + [0xffb3] = 0x51, /* 65459 (XK_KP_3) => 81 via 81 (KEY_KP3) */ + [0xffb4] = 0x4b, /* 65460 (XK_KP_4) => 75 via 75 (KEY_KP4) */ + [0xffb5] = 0x4c, /* 65461 (XK_KP_5) => 76 via 76 (KEY_KP5) */ + [0xffb6] = 0x4d, /* 65462 (XK_KP_6) => 77 via 77 (KEY_KP6) */ + [0xffb7] = 0x47, /* 65463 (XK_KP_7) => 71 via 71 (KEY_KP7) */ + [0xffb8] = 0x48, /* 65464 (XK_KP_8) => 72 via 72 (KEY_KP8) */ + [0xffb9] = 0x49, /* 65465 (XK_KP_9) => 73 via 73 (KEY_KP9) */ + [0xffbd] = 0x59, /* 65469 (XK_KP_Equal) => 89 via 117 (KEY_KPEQUAL) */ + [0xffbe] = 0x3b, /* 65470 (XK_F1) => 59 via 59 (KEY_F1) */ + [0xffbf] = 0x3c, /* 65471 (XK_F2) => 60 via 60 (KEY_F2) */ + [0xffc0] = 0x3d, /* 65472 (XK_F3) => 61 via 61 (KEY_F3) */ + [0xffc1] = 0x3e, /* 65473 (XK_F4) => 62 via 62 (KEY_F4) */ + [0xffc2] = 0x3f, /* 65474 (XK_F5) => 63 via 63 (KEY_F5) */ + [0xffc3] = 0x40, /* 65475 (XK_F6) => 64 via 64 (KEY_F6) */ + [0xffc4] = 0x41, /* 65476 (XK_F7) => 65 via 65 (KEY_F7) */ + [0xffc5] = 0x42, /* 65477 (XK_F8) => 66 via 66 (KEY_F8) */ + [0xffc6] = 0x43, /* 65478 (XK_F9) => 67 via 67 (KEY_F9) */ + [0xffc7] = 0x44, /* 65479 (XK_F10) => 68 via 68 (KEY_F10) */ + [0xffe1] = 0x2a, /* 65505 (XK_Shift_L) => 42 via 42 (KEY_LEFTSHIFT) */ + [0xffe2] = 0x36, /* 65506 (XK_Shift_R) => 54 via 54 (KEY_RIGHTSHIFT) */ + [0xffe3] = 0x1d, /* 65507 (XK_Control_L) => 29 via 29 (KEY_LEFTCTRL) */ + [0xffe4] = 0x11d, /* 65508 (XK_Control_R) => 285 via 97 (KEY_RIGHTCTRL) */ + [0xffe5] = 0x3a, /* 65509 (XK_Caps_Lock) => 58 via 58 (KEY_CAPSLOCK) */ + [0xffe7] = 0x15b, /* 65511 (XK_Meta_L) => 347 via 125 (KEY_LEFTMETA) */ + [0xffe8] = 0x15c, /* 65512 (XK_Meta_R) => 348 via 126 (KEY_RIGHTMETA) */ + [0xffe9] = 0x38, /* 65513 (XK_Alt_L) => 56 via 56 (KEY_LEFTALT) */ + [0xffea] = 0x138, /* 65514 (XK_Alt_R) => 312 via 100 (KEY_RIGHTALT) */ + [0xffff] = 0x153, /* 65535 (XK_Delete) => 339 via 111 (KEY_DELETE) */ +}; diff --git a/src/vncdisplaykeymap_xorgevdev2xtkbd.c b/src/vncdisplaykeymap_xorgevdev2xtkbd.c new file mode 100644 index 0000000..ffa8c45 --- /dev/null +++ b/src/vncdisplaykeymap_xorgevdev2xtkbd.c @@ -0,0 +1,240 @@ +static const guint16 keymap_xorgevdev2xtkbd[] = { + [0x9] = 0x1, /* 9 => 1 via 1 (KEY_ESC) */ + [0xa] = 0x2, /* 10 => 2 via 2 (KEY_1) */ + [0xb] = 0x3, /* 11 => 3 via 3 (KEY_2) */ + [0xc] = 0x4, /* 12 => 4 via 4 (KEY_3) */ + [0xd] = 0x5, /* 13 => 5 via 5 (KEY_4) */ + [0xe] = 0x6, /* 14 => 6 via 6 (KEY_5) */ + [0xf] = 0x7, /* 15 => 7 via 7 (KEY_6) */ + [0x10] = 0x8, /* 16 => 8 via 8 (KEY_7) */ + [0x11] = 0x9, /* 17 => 9 via 9 (KEY_8) */ + [0x12] = 0xa, /* 18 => 10 via 10 (KEY_9) */ + [0x13] = 0xb, /* 19 => 11 via 11 (KEY_0) */ + [0x14] = 0xc, /* 20 => 12 via 12 (KEY_MINUS) */ + [0x15] = 0xd, /* 21 => 13 via 13 (KEY_EQUAL) */ + [0x16] = 0xe, /* 22 => 14 via 14 (KEY_BACKSPACE) */ + [0x17] = 0xf, /* 23 => 15 via 15 (KEY_TAB) */ + [0x18] = 0x10, /* 24 => 16 via 16 (KEY_Q) */ + [0x19] = 0x11, /* 25 => 17 via 17 (KEY_W) */ + [0x1a] = 0x12, /* 26 => 18 via 18 (KEY_E) */ + [0x1b] = 0x13, /* 27 => 19 via 19 (KEY_R) */ + [0x1c] = 0x14, /* 28 => 20 via 20 (KEY_T) */ + [0x1d] = 0x15, /* 29 => 21 via 21 (KEY_Y) */ + [0x1e] = 0x16, /* 30 => 22 via 22 (KEY_U) */ + [0x1f] = 0x17, /* 31 => 23 via 23 (KEY_I) */ + [0x20] = 0x18, /* 32 => 24 via 24 (KEY_O) */ + [0x21] = 0x19, /* 33 => 25 via 25 (KEY_P) */ + [0x22] = 0x1a, /* 34 => 26 via 26 (KEY_LEFTBRACE) */ + [0x23] = 0x1b, /* 35 => 27 via 27 (KEY_RIGHTBRACE) */ + [0x24] = 0x1c, /* 36 => 28 via 28 (KEY_ENTER) */ + [0x25] = 0x1d, /* 37 => 29 via 29 (KEY_LEFTCTRL) */ + [0x26] = 0x1e, /* 38 => 30 via 30 (KEY_A) */ + [0x27] = 0x1f, /* 39 => 31 via 31 (KEY_S) */ + [0x28] = 0x20, /* 40 => 32 via 32 (KEY_D) */ + [0x29] = 0x21, /* 41 => 33 via 33 (KEY_F) */ + [0x2a] = 0x22, /* 42 => 34 via 34 (KEY_G) */ + [0x2b] = 0x23, /* 43 => 35 via 35 (KEY_H) */ + [0x2c] = 0x24, /* 44 => 36 via 36 (KEY_J) */ + [0x2d] = 0x25, /* 45 => 37 via 37 (KEY_K) */ + [0x2e] = 0x26, /* 46 => 38 via 38 (KEY_L) */ + [0x2f] = 0x27, /* 47 => 39 via 39 (KEY_SEMICOLON) */ + [0x30] = 0x28, /* 48 => 40 via 40 (KEY_APOSTROPHE) */ + [0x31] = 0x29, /* 49 => 41 via 41 (KEY_GRAVE) */ + [0x32] = 0x2a, /* 50 => 42 via 42 (KEY_LEFTSHIFT) */ + [0x33] = 0x2b, /* 51 => 43 via 43 (KEY_BACKSLASH) */ + [0x34] = 0x2c, /* 52 => 44 via 44 (KEY_Z) */ + [0x35] = 0x2d, /* 53 => 45 via 45 (KEY_X) */ + [0x36] = 0x2e, /* 54 => 46 via 46 (KEY_C) */ + [0x37] = 0x2f, /* 55 => 47 via 47 (KEY_V) */ + [0x38] = 0x30, /* 56 => 48 via 48 (KEY_B) */ + [0x39] = 0x31, /* 57 => 49 via 49 (KEY_N) */ + [0x3a] = 0x32, /* 58 => 50 via 50 (KEY_M) */ + [0x3b] = 0x33, /* 59 => 51 via 51 (KEY_COMMA) */ + [0x3c] = 0x34, /* 60 => 52 via 52 (KEY_DOT) */ + [0x3d] = 0x35, /* 61 => 53 via 53 (KEY_SLASH) */ + [0x3e] = 0x36, /* 62 => 54 via 54 (KEY_RIGHTSHIFT) */ + [0x3f] = 0x37, /* 63 => 55 via 55 (KEY_KPASTERISK) */ + [0x40] = 0x38, /* 64 => 56 via 56 (KEY_LEFTALT) */ + [0x41] = 0x39, /* 65 => 57 via 57 (KEY_SPACE) */ + [0x42] = 0x3a, /* 66 => 58 via 58 (KEY_CAPSLOCK) */ + [0x43] = 0x3b, /* 67 => 59 via 59 (KEY_F1) */ + [0x44] = 0x3c, /* 68 => 60 via 60 (KEY_F2) */ + [0x45] = 0x3d, /* 69 => 61 via 61 (KEY_F3) */ + [0x46] = 0x3e, /* 70 => 62 via 62 (KEY_F4) */ + [0x47] = 0x3f, /* 71 => 63 via 63 (KEY_F5) */ + [0x48] = 0x40, /* 72 => 64 via 64 (KEY_F6) */ + [0x49] = 0x41, /* 73 => 65 via 65 (KEY_F7) */ + [0x4a] = 0x42, /* 74 => 66 via 66 (KEY_F8) */ + [0x4b] = 0x43, /* 75 => 67 via 67 (KEY_F9) */ + [0x4c] = 0x44, /* 76 => 68 via 68 (KEY_F10) */ + [0x4d] = 0x45, /* 77 => 69 via 69 (KEY_NUMLOCK) */ + [0x4e] = 0x46, /* 78 => 70 via 70 (KEY_SCROLLLOCK) */ + [0x4f] = 0x47, /* 79 => 71 via 71 (KEY_KP7) */ + [0x50] = 0x48, /* 80 => 72 via 72 (KEY_KP8) */ + [0x51] = 0x49, /* 81 => 73 via 73 (KEY_KP9) */ + [0x52] = 0x4a, /* 82 => 74 via 74 (KEY_KPMINUS) */ + [0x53] = 0x4b, /* 83 => 75 via 75 (KEY_KP4) */ + [0x54] = 0x4c, /* 84 => 76 via 76 (KEY_KP5) */ + [0x55] = 0x4d, /* 85 => 77 via 77 (KEY_KP6) */ + [0x56] = 0x4e, /* 86 => 78 via 78 (KEY_KPPLUS) */ + [0x57] = 0x4f, /* 87 => 79 via 79 (KEY_KP1) */ + [0x58] = 0x50, /* 88 => 80 via 80 (KEY_KP2) */ + [0x59] = 0x51, /* 89 => 81 via 81 (KEY_KP3) */ + [0x5a] = 0x52, /* 90 => 82 via 82 (KEY_KP0) */ + [0x5b] = 0x53, /* 91 => 83 via 83 (KEY_KPDOT) */ + [0x5c] = 0x54, /* 92 => 84 via 84 */ + [0x5d] = 0x76, /* 93 => 118 via 85 (KEY_ZENKAKUHANKAKU) */ + [0x5e] = 0x56, /* 94 => 86 via 86 (KEY_102ND) */ + [0x5f] = 0x57, /* 95 => 87 via 87 (KEY_F11) */ + [0x60] = 0x58, /* 96 => 88 via 88 (KEY_F12) */ + [0x61] = 0x73, /* 97 => 115 via 89 (KEY_RO) */ + [0x62] = 0x78, /* 98 => 120 via 90 (KEY_KATAKANA) */ + [0x63] = 0x77, /* 99 => 119 via 91 (KEY_HIRAGANA) */ + [0x64] = 0x79, /* 100 => 121 via 92 (KEY_HENKAN) */ + [0x65] = 0x70, /* 101 => 112 via 93 (KEY_KATAKANAHIRAGANA) */ + [0x66] = 0x7b, /* 102 => 123 via 94 (KEY_MUHENKAN) */ + [0x67] = 0x5c, /* 103 => 92 via 95 (KEY_KPJPCOMMA) */ + [0x68] = 0x11c, /* 104 => 284 via 96 (KEY_KPENTER) */ + [0x69] = 0x11d, /* 105 => 285 via 97 (KEY_RIGHTCTRL) */ + [0x6a] = 0x135, /* 106 => 309 via 98 (KEY_KPSLASH) */ + [0x6b] = 0x54, /* 107 => 84 via 99 (KEY_SYSRQ) */ + [0x6c] = 0x138, /* 108 => 312 via 100 (KEY_RIGHTALT) */ + [0x6d] = 0x5b, /* 109 => 91 via 101 (KEY_LINEFEED) */ + [0x6e] = 0x147, /* 110 => 327 via 102 (KEY_HOME) */ + [0x6f] = 0x148, /* 111 => 328 via 103 (KEY_UP) */ + [0x70] = 0x149, /* 112 => 329 via 104 (KEY_PAGEUP) */ + [0x71] = 0x14b, /* 113 => 331 via 105 (KEY_LEFT) */ + [0x72] = 0x14d, /* 114 => 333 via 106 (KEY_RIGHT) */ + [0x73] = 0x14f, /* 115 => 335 via 107 (KEY_END) */ + [0x74] = 0x150, /* 116 => 336 via 108 (KEY_DOWN) */ + [0x75] = 0x151, /* 117 => 337 via 109 (KEY_PAGEDOWN) */ + [0x76] = 0x152, /* 118 => 338 via 110 (KEY_INSERT) */ + [0x77] = 0x153, /* 119 => 339 via 111 (KEY_DELETE) */ + [0x78] = 0x16f, /* 120 => 367 via 112 (KEY_MACRO) */ + [0x79] = 0x120, /* 121 => 288 via 113 (KEY_MUTE) */ + [0x7a] = 0x12e, /* 122 => 302 via 114 (KEY_VOLUMEDOWN) */ + [0x7b] = 0x130, /* 123 => 304 via 115 (KEY_VOLUMEUP) */ + [0x7c] = 0x15e, /* 124 => 350 via 116 (KEY_POWER) */ + [0x7d] = 0x59, /* 125 => 89 via 117 (KEY_KPEQUAL) */ + [0x7e] = 0x14e, /* 126 => 334 via 118 (KEY_KPPLUSMINUS) */ + [0x7f] = 0x146, /* 127 => 326 via 119 (KEY_PAUSE) */ + [0x80] = 0x10b, /* 128 => 267 via 120 (KEY_SCALE) */ + [0x81] = 0x7e, /* 129 => 126 via 121 (KEY_KPCOMMA) */ + [0x83] = 0x10d, /* 131 => 269 via 123 (KEY_HANJA) */ + [0x84] = 0x7d, /* 132 => 125 via 124 (KEY_YEN) */ + [0x85] = 0x15b, /* 133 => 347 via 125 (KEY_LEFTMETA) */ + [0x86] = 0x15c, /* 134 => 348 via 126 (KEY_RIGHTMETA) */ + [0x87] = 0x15d, /* 135 => 349 via 127 (KEY_COMPOSE) */ + [0x88] = 0x168, /* 136 => 360 via 128 (KEY_STOP) */ + [0x89] = 0x105, /* 137 => 261 via 129 (KEY_AGAIN) */ + [0x8a] = 0x106, /* 138 => 262 via 130 (KEY_PROPS) */ + [0x8b] = 0x107, /* 139 => 263 via 131 (KEY_UNDO) */ + [0x8c] = 0x10c, /* 140 => 268 via 132 (KEY_FRONT) */ + [0x8d] = 0x178, /* 141 => 376 via 133 (KEY_COPY) */ + [0x8e] = 0x64, /* 142 => 100 via 134 (KEY_OPEN) */ + [0x8f] = 0x65, /* 143 => 101 via 135 (KEY_PASTE) */ + [0x90] = 0x141, /* 144 => 321 via 136 (KEY_FIND) */ + [0x91] = 0x13c, /* 145 => 316 via 137 (KEY_CUT) */ + [0x92] = 0x175, /* 146 => 373 via 138 (KEY_HELP) */ + [0x93] = 0x11e, /* 147 => 286 via 139 (KEY_MENU) */ + [0x94] = 0x121, /* 148 => 289 via 140 (KEY_CALC) */ + [0x95] = 0x66, /* 149 => 102 via 141 (KEY_SETUP) */ + [0x96] = 0x15f, /* 150 => 351 via 142 (KEY_SLEEP) */ + [0x97] = 0x163, /* 151 => 355 via 143 (KEY_WAKEUP) */ + [0x98] = 0x67, /* 152 => 103 via 144 (KEY_FILE) */ + [0x99] = 0x68, /* 153 => 104 via 145 (KEY_SENDFILE) */ + [0x9a] = 0x69, /* 154 => 105 via 146 (KEY_DELETEFILE) */ + [0x9b] = 0x113, /* 155 => 275 via 147 (KEY_XFER) */ + [0x9c] = 0x11f, /* 156 => 287 via 148 (KEY_PROG1) */ + [0x9d] = 0x117, /* 157 => 279 via 149 (KEY_PROG2) */ + [0x9e] = 0x102, /* 158 => 258 via 150 (KEY_WWW) */ + [0x9f] = 0x6a, /* 159 => 106 via 151 (KEY_MSDOS) */ + [0xa0] = 0x112, /* 160 => 274 via 152 (KEY_SCREENLOCK) */ + [0xa1] = 0x6b, /* 161 => 107 via 153 (KEY_DIRECTION) */ + [0xa2] = 0x126, /* 162 => 294 via 154 (KEY_CYCLEWINDOWS) */ + [0xa3] = 0x16c, /* 163 => 364 via 155 (KEY_MAIL) */ + [0xa4] = 0x166, /* 164 => 358 via 156 (KEY_BOOKMARKS) */ + [0xa5] = 0x16b, /* 165 => 363 via 157 (KEY_COMPUTER) */ + [0xa6] = 0x16a, /* 166 => 362 via 158 (KEY_BACK) */ + [0xa7] = 0x169, /* 167 => 361 via 159 (KEY_FORWARD) */ + [0xa8] = 0x123, /* 168 => 291 via 160 (KEY_CLOSECD) */ + [0xa9] = 0x6c, /* 169 => 108 via 161 (KEY_EJECTCD) */ + [0xaa] = 0x17d, /* 170 => 381 via 162 (KEY_EJECTCLOSECD) */ + [0xab] = 0x119, /* 171 => 281 via 163 (KEY_NEXTSONG) */ + [0xac] = 0x122, /* 172 => 290 via 164 (KEY_PLAYPAUSE) */ + [0xad] = 0x110, /* 173 => 272 via 165 (KEY_PREVIOUSSONG) */ + [0xae] = 0x124, /* 174 => 292 via 166 (KEY_STOPCD) */ + [0xaf] = 0x131, /* 175 => 305 via 167 (KEY_RECORD) */ + [0xb0] = 0x118, /* 176 => 280 via 168 (KEY_REWIND) */ + [0xb1] = 0x63, /* 177 => 99 via 169 (KEY_PHONE) */ + [0xb2] = 0x70, /* 178 => 112 via 170 (KEY_ISO) */ + [0xb3] = 0x101, /* 179 => 257 via 171 (KEY_CONFIG) */ + [0xb4] = 0x132, /* 180 => 306 via 172 (KEY_HOMEPAGE) */ + [0xb5] = 0x167, /* 181 => 359 via 173 (KEY_REFRESH) */ + [0xb6] = 0x71, /* 182 => 113 via 174 (KEY_EXIT) */ + [0xb7] = 0x72, /* 183 => 114 via 175 (KEY_MOVE) */ + [0xb8] = 0x108, /* 184 => 264 via 176 (KEY_EDIT) */ + [0xb9] = 0x75, /* 185 => 117 via 177 (KEY_SCROLLUP) */ + [0xba] = 0x10f, /* 186 => 271 via 178 (KEY_SCROLLDOWN) */ + [0xbb] = 0x176, /* 187 => 374 via 179 (KEY_KPLEFTPAREN) */ + [0xbc] = 0x17b, /* 188 => 379 via 180 (KEY_KPRIGHTPAREN) */ + [0xbd] = 0x109, /* 189 => 265 via 181 (KEY_NEW) */ + [0xbe] = 0x10a, /* 190 => 266 via 182 (KEY_REDO) */ + [0xbf] = 0x5d, /* 191 => 93 via 183 (KEY_F13) */ + [0xc0] = 0x5e, /* 192 => 94 via 184 (KEY_F14) */ + [0xc1] = 0x5f, /* 193 => 95 via 185 (KEY_F15) */ + [0xc2] = 0x55, /* 194 => 85 via 186 (KEY_F16) */ + [0xc3] = 0x103, /* 195 => 259 via 187 (KEY_F17) */ + [0xc4] = 0x177, /* 196 => 375 via 188 (KEY_F18) */ + [0xc5] = 0x104, /* 197 => 260 via 189 (KEY_F19) */ + [0xc6] = 0x5a, /* 198 => 90 via 190 (KEY_F20) */ + [0xc7] = 0x74, /* 199 => 116 via 191 (KEY_F21) */ + [0xc8] = 0x179, /* 200 => 377 via 192 (KEY_F22) */ + [0xc9] = 0x6d, /* 201 => 109 via 193 (KEY_F23) */ + [0xca] = 0x6f, /* 202 => 111 via 194 (KEY_F24) */ + [0xcb] = 0x115, /* 203 => 277 via 195 */ + [0xcc] = 0x116, /* 204 => 278 via 196 */ + [0xcd] = 0x11a, /* 205 => 282 via 197 */ + [0xce] = 0x11b, /* 206 => 283 via 198 */ + [0xcf] = 0x127, /* 207 => 295 via 199 */ + [0xd0] = 0x128, /* 208 => 296 via 200 (KEY_PLAYCD) */ + [0xd1] = 0x129, /* 209 => 297 via 201 (KEY_PAUSECD) */ + [0xd2] = 0x12b, /* 210 => 299 via 202 (KEY_PROG3) */ + [0xd3] = 0x12c, /* 211 => 300 via 203 (KEY_PROG4) */ + [0xd4] = 0x12d, /* 212 => 301 via 204 (KEY_DASHBOARD) */ + [0xd5] = 0x125, /* 213 => 293 via 205 (KEY_SUSPEND) */ + [0xd6] = 0x12f, /* 214 => 303 via 206 (KEY_CLOSE) */ + [0xd7] = 0x133, /* 215 => 307 via 207 (KEY_PLAY) */ + [0xd8] = 0x134, /* 216 => 308 via 208 (KEY_FASTFORWARD) */ + [0xd9] = 0x136, /* 217 => 310 via 209 (KEY_BASSBOOST) */ + [0xda] = 0x139, /* 218 => 313 via 210 (KEY_PRINT) */ + [0xdb] = 0x13a, /* 219 => 314 via 211 (KEY_HP) */ + [0xdc] = 0x13b, /* 220 => 315 via 212 (KEY_CAMERA) */ + [0xdd] = 0x13d, /* 221 => 317 via 213 (KEY_SOUND) */ + [0xde] = 0x13e, /* 222 => 318 via 214 (KEY_QUESTION) */ + [0xdf] = 0x13f, /* 223 => 319 via 215 (KEY_EMAIL) */ + [0xe0] = 0x140, /* 224 => 320 via 216 (KEY_CHAT) */ + [0xe1] = 0x165, /* 225 => 357 via 217 (KEY_SEARCH) */ + [0xe2] = 0x142, /* 226 => 322 via 218 (KEY_CONNECT) */ + [0xe3] = 0x143, /* 227 => 323 via 219 (KEY_FINANCE) */ + [0xe4] = 0x144, /* 228 => 324 via 220 (KEY_SPORT) */ + [0xe5] = 0x145, /* 229 => 325 via 221 (KEY_SHOP) */ + [0xe6] = 0x114, /* 230 => 276 via 222 (KEY_ALTERASE) */ + [0xe7] = 0x14a, /* 231 => 330 via 223 (KEY_CANCEL) */ + [0xe8] = 0x14c, /* 232 => 332 via 224 (KEY_BRIGHTNESSDOWN) */ + [0xe9] = 0x154, /* 233 => 340 via 225 (KEY_BRIGHTNESSUP) */ + [0xea] = 0x16d, /* 234 => 365 via 226 (KEY_MEDIA) */ + [0xeb] = 0x156, /* 235 => 342 via 227 (KEY_SWITCHVIDEOMODE) */ + [0xec] = 0x157, /* 236 => 343 via 228 (KEY_KBDILLUMTOGGLE) */ + [0xed] = 0x158, /* 237 => 344 via 229 (KEY_KBDILLUMDOWN) */ + [0xee] = 0x159, /* 238 => 345 via 230 (KEY_KBDILLUMUP) */ + [0xef] = 0x15a, /* 239 => 346 via 231 (KEY_SEND) */ + [0xf0] = 0x164, /* 240 => 356 via 232 (KEY_REPLY) */ + [0xf1] = 0x10e, /* 241 => 270 via 233 (KEY_FORWARDMAIL) */ + [0xf2] = 0x155, /* 242 => 341 via 234 (KEY_SAVE) */ + [0xf3] = 0x170, /* 243 => 368 via 235 (KEY_DOCUMENTS) */ + [0xf4] = 0x171, /* 244 => 369 via 236 (KEY_BATTERY) */ + [0xf5] = 0x172, /* 245 => 370 via 237 (KEY_BLUETOOTH) */ + [0xf6] = 0x173, /* 246 => 371 via 238 (KEY_WLAN) */ + [0xf7] = 0x174, /* 247 => 372 via 239 (KEY_UWB) */ +}; diff --git a/src/vncdisplaykeymap_xorgkbd2xtkbd.c b/src/vncdisplaykeymap_xorgkbd2xtkbd.c new file mode 100644 index 0000000..a455eeb --- /dev/null +++ b/src/vncdisplaykeymap_xorgkbd2xtkbd.c @@ -0,0 +1,112 @@ +static const guint16 keymap_xorgkbd2xtkbd[] = { + [0x9] = 0x1, /* 9 => 1 via 1 (KEY_ESC) */ + [0xa] = 0x2, /* 10 => 2 via 2 (KEY_1) */ + [0xb] = 0x3, /* 11 => 3 via 3 (KEY_2) */ + [0xc] = 0x4, /* 12 => 4 via 4 (KEY_3) */ + [0xd] = 0x5, /* 13 => 5 via 5 (KEY_4) */ + [0xe] = 0x6, /* 14 => 6 via 6 (KEY_5) */ + [0xf] = 0x7, /* 15 => 7 via 7 (KEY_6) */ + [0x10] = 0x8, /* 16 => 8 via 8 (KEY_7) */ + [0x11] = 0x9, /* 17 => 9 via 9 (KEY_8) */ + [0x12] = 0xa, /* 18 => 10 via 10 (KEY_9) */ + [0x13] = 0xb, /* 19 => 11 via 11 (KEY_0) */ + [0x14] = 0xc, /* 20 => 12 via 12 (KEY_MINUS) */ + [0x15] = 0xd, /* 21 => 13 via 13 (KEY_EQUAL) */ + [0x16] = 0xe, /* 22 => 14 via 14 (KEY_BACKSPACE) */ + [0x17] = 0xf, /* 23 => 15 via 15 (KEY_TAB) */ + [0x18] = 0x10, /* 24 => 16 via 16 (KEY_Q) */ + [0x19] = 0x11, /* 25 => 17 via 17 (KEY_W) */ + [0x1a] = 0x12, /* 26 => 18 via 18 (KEY_E) */ + [0x1b] = 0x13, /* 27 => 19 via 19 (KEY_R) */ + [0x1c] = 0x14, /* 28 => 20 via 20 (KEY_T) */ + [0x1d] = 0x15, /* 29 => 21 via 21 (KEY_Y) */ + [0x1e] = 0x16, /* 30 => 22 via 22 (KEY_U) */ + [0x1f] = 0x17, /* 31 => 23 via 23 (KEY_I) */ + [0x20] = 0x18, /* 32 => 24 via 24 (KEY_O) */ + [0x21] = 0x19, /* 33 => 25 via 25 (KEY_P) */ + [0x22] = 0x1a, /* 34 => 26 via 26 (KEY_LEFTBRACE) */ + [0x23] = 0x1b, /* 35 => 27 via 27 (KEY_RIGHTBRACE) */ + [0x24] = 0x1c, /* 36 => 28 via 28 (KEY_ENTER) */ + [0x25] = 0x1d, /* 37 => 29 via 29 (KEY_LEFTCTRL) */ + [0x26] = 0x1e, /* 38 => 30 via 30 (KEY_A) */ + [0x27] = 0x1f, /* 39 => 31 via 31 (KEY_S) */ + [0x28] = 0x20, /* 40 => 32 via 32 (KEY_D) */ + [0x29] = 0x21, /* 41 => 33 via 33 (KEY_F) */ + [0x2a] = 0x22, /* 42 => 34 via 34 (KEY_G) */ + [0x2b] = 0x23, /* 43 => 35 via 35 (KEY_H) */ + [0x2c] = 0x24, /* 44 => 36 via 36 (KEY_J) */ + [0x2d] = 0x25, /* 45 => 37 via 37 (KEY_K) */ + [0x2e] = 0x26, /* 46 => 38 via 38 (KEY_L) */ + [0x2f] = 0x27, /* 47 => 39 via 39 (KEY_SEMICOLON) */ + [0x30] = 0x28, /* 48 => 40 via 40 (KEY_APOSTROPHE) */ + [0x31] = 0x29, /* 49 => 41 via 41 (KEY_GRAVE) */ + [0x32] = 0x2a, /* 50 => 42 via 42 (KEY_LEFTSHIFT) */ + [0x33] = 0x2b, /* 51 => 43 via 43 (KEY_BACKSLASH) */ + [0x34] = 0x2c, /* 52 => 44 via 44 (KEY_Z) */ + [0x35] = 0x2d, /* 53 => 45 via 45 (KEY_X) */ + [0x36] = 0x2e, /* 54 => 46 via 46 (KEY_C) */ + [0x37] = 0x2f, /* 55 => 47 via 47 (KEY_V) */ + [0x38] = 0x30, /* 56 => 48 via 48 (KEY_B) */ + [0x39] = 0x31, /* 57 => 49 via 49 (KEY_N) */ + [0x3a] = 0x32, /* 58 => 50 via 50 (KEY_M) */ + [0x3b] = 0x33, /* 59 => 51 via 51 (KEY_COMMA) */ + [0x3c] = 0x34, /* 60 => 52 via 52 (KEY_DOT) */ + [0x3d] = 0x35, /* 61 => 53 via 53 (KEY_SLASH) */ + [0x3e] = 0x36, /* 62 => 54 via 54 (KEY_RIGHTSHIFT) */ + [0x3f] = 0x37, /* 63 => 55 via 55 (KEY_KPASTERISK) */ + [0x40] = 0x38, /* 64 => 56 via 56 (KEY_LEFTALT) */ + [0x41] = 0x39, /* 65 => 57 via 57 (KEY_SPACE) */ + [0x42] = 0x3a, /* 66 => 58 via 58 (KEY_CAPSLOCK) */ + [0x43] = 0x3b, /* 67 => 59 via 59 (KEY_F1) */ + [0x44] = 0x3c, /* 68 => 60 via 60 (KEY_F2) */ + [0x45] = 0x3d, /* 69 => 61 via 61 (KEY_F3) */ + [0x46] = 0x3e, /* 70 => 62 via 62 (KEY_F4) */ + [0x47] = 0x3f, /* 71 => 63 via 63 (KEY_F5) */ + [0x48] = 0x40, /* 72 => 64 via 64 (KEY_F6) */ + [0x49] = 0x41, /* 73 => 65 via 65 (KEY_F7) */ + [0x4a] = 0x42, /* 74 => 66 via 66 (KEY_F8) */ + [0x4b] = 0x43, /* 75 => 67 via 67 (KEY_F9) */ + [0x4c] = 0x44, /* 76 => 68 via 68 (KEY_F10) */ + [0x4d] = 0x45, /* 77 => 69 via 69 (KEY_NUMLOCK) */ + [0x4e] = 0x46, /* 78 => 70 via 70 (KEY_SCROLLLOCK) */ + [0x4f] = 0x47, /* 79 => 71 via 71 (KEY_KP7) */ + [0x50] = 0x48, /* 80 => 72 via 72 (KEY_KP8) */ + [0x51] = 0x49, /* 81 => 73 via 73 (KEY_KP9) */ + [0x52] = 0x4a, /* 82 => 74 via 74 (KEY_KPMINUS) */ + [0x53] = 0x4b, /* 83 => 75 via 75 (KEY_KP4) */ + [0x54] = 0x4c, /* 84 => 76 via 76 (KEY_KP5) */ + [0x55] = 0x4d, /* 85 => 77 via 77 (KEY_KP6) */ + [0x56] = 0x4e, /* 86 => 78 via 78 (KEY_KPPLUS) */ + [0x57] = 0x4f, /* 87 => 79 via 79 (KEY_KP1) */ + [0x58] = 0x50, /* 88 => 80 via 80 (KEY_KP2) */ + [0x59] = 0x51, /* 89 => 81 via 81 (KEY_KP3) */ + [0x5a] = 0x52, /* 90 => 82 via 82 (KEY_KP0) */ + [0x5b] = 0x53, /* 91 => 83 via 83 (KEY_KPDOT) */ + [0x61] = 0x147, /* 97 => 327 via 102 (KEY_HOME) */ + [0x62] = 0x148, /* 98 => 328 via 103 (KEY_UP) */ + [0x63] = 0x149, /* 99 => 329 via 104 (KEY_PAGEUP) */ + [0x64] = 0x14b, /* 100 => 331 via 105 (KEY_LEFT) */ + [0x66] = 0x14d, /* 102 => 333 via 106 (KEY_RIGHT) */ + [0x67] = 0x14f, /* 103 => 335 via 107 (KEY_END) */ + [0x68] = 0x150, /* 104 => 336 via 108 (KEY_DOWN) */ + [0x69] = 0x151, /* 105 => 337 via 109 (KEY_PAGEDOWN) */ + [0x6a] = 0x152, /* 106 => 338 via 110 (KEY_INSERT) */ + [0x6b] = 0x153, /* 107 => 339 via 111 (KEY_DELETE) */ + [0x6c] = 0x11c, /* 108 => 284 via 96 (KEY_KPENTER) */ + [0x6d] = 0x11d, /* 109 => 285 via 97 (KEY_RIGHTCTRL) */ + [0x6e] = 0x146, /* 110 => 326 via 119 (KEY_PAUSE) */ + [0x6f] = 0x54, /* 111 => 84 via 99 (KEY_SYSRQ) */ + [0x70] = 0x135, /* 112 => 309 via 98 (KEY_KPSLASH) */ + [0x71] = 0x138, /* 113 => 312 via 100 (KEY_RIGHTALT) */ + [0x73] = 0x15b, /* 115 => 347 via 125 (KEY_LEFTMETA) */ + [0x74] = 0x15c, /* 116 => 348 via 126 (KEY_RIGHTMETA) */ + [0x75] = 0x15d, /* 117 => 349 via 127 (KEY_COMPOSE) */ + [0x76] = 0x5d, /* 118 => 93 via 183 (KEY_F13) */ + [0x77] = 0x5e, /* 119 => 94 via 184 (KEY_F14) */ + [0x78] = 0x5f, /* 120 => 95 via 185 (KEY_F15) */ + [0x79] = 0x55, /* 121 => 85 via 186 (KEY_F16) */ + [0x7a] = 0x103, /* 122 => 259 via 187 (KEY_F17) */ + [0x7e] = 0x59, /* 126 => 89 via 117 (KEY_KPEQUAL) */ + [0x85] = 0x7d, /* 133 => 125 via 124 (KEY_YEN) */ + [0xd0] = 0x70, /* 208 => 112 via 93 (KEY_KATAKANAHIRAGANA) */ +}; diff --git a/src/vncdisplaykeymap_xorgxquartz2xtkbd.c b/src/vncdisplaykeymap_xorgxquartz2xtkbd.c new file mode 100644 index 0000000..76e6d47 --- /dev/null +++ b/src/vncdisplaykeymap_xorgxquartz2xtkbd.c @@ -0,0 +1,117 @@ +static const guint16 keymap_xorgxquartz2xtkbd[] = { + [0x8] = 0x1e, /* 8 => 30 via 30 (KEY_A) */ + [0x9] = 0x1f, /* 9 => 31 via 31 (KEY_S) */ + [0xa] = 0x20, /* 10 => 32 via 32 (KEY_D) */ + [0xb] = 0x21, /* 11 => 33 via 33 (KEY_F) */ + [0xc] = 0x23, /* 12 => 35 via 35 (KEY_H) */ + [0xd] = 0x22, /* 13 => 34 via 34 (KEY_G) */ + [0xe] = 0x2c, /* 14 => 44 via 44 (KEY_Z) */ + [0xf] = 0x2d, /* 15 => 45 via 45 (KEY_X) */ + [0x10] = 0x2e, /* 16 => 46 via 46 (KEY_C) */ + [0x11] = 0x2f, /* 17 => 47 via 47 (KEY_V) */ + [0x12] = 0x70, /* 18 => 112 via 170 (KEY_ISO) */ + [0x13] = 0x30, /* 19 => 48 via 48 (KEY_B) */ + [0x14] = 0x10, /* 20 => 16 via 16 (KEY_Q) */ + [0x15] = 0x11, /* 21 => 17 via 17 (KEY_W) */ + [0x16] = 0x12, /* 22 => 18 via 18 (KEY_E) */ + [0x17] = 0x13, /* 23 => 19 via 19 (KEY_R) */ + [0x18] = 0x15, /* 24 => 21 via 21 (KEY_Y) */ + [0x19] = 0x14, /* 25 => 20 via 20 (KEY_T) */ + [0x1a] = 0x2, /* 26 => 2 via 2 (KEY_1) */ + [0x1b] = 0x3, /* 27 => 3 via 3 (KEY_2) */ + [0x1c] = 0x4, /* 28 => 4 via 4 (KEY_3) */ + [0x1d] = 0x5, /* 29 => 5 via 5 (KEY_4) */ + [0x1e] = 0x7, /* 30 => 7 via 7 (KEY_6) */ + [0x1f] = 0x6, /* 31 => 6 via 6 (KEY_5) */ + [0x20] = 0xd, /* 32 => 13 via 13 (KEY_EQUAL) */ + [0x21] = 0xa, /* 33 => 10 via 10 (KEY_9) */ + [0x22] = 0x8, /* 34 => 8 via 8 (KEY_7) */ + [0x23] = 0xc, /* 35 => 12 via 12 (KEY_MINUS) */ + [0x24] = 0x9, /* 36 => 9 via 9 (KEY_8) */ + [0x25] = 0xb, /* 37 => 11 via 11 (KEY_0) */ + [0x26] = 0x1b, /* 38 => 27 via 27 (KEY_RIGHTBRACE) */ + [0x27] = 0x18, /* 39 => 24 via 24 (KEY_O) */ + [0x28] = 0x16, /* 40 => 22 via 22 (KEY_U) */ + [0x29] = 0x1a, /* 41 => 26 via 26 (KEY_LEFTBRACE) */ + [0x2a] = 0x17, /* 42 => 23 via 23 (KEY_I) */ + [0x2b] = 0x19, /* 43 => 25 via 25 (KEY_P) */ + [0x2c] = 0x1c, /* 44 => 28 via 28 (KEY_ENTER) */ + [0x2d] = 0x26, /* 45 => 38 via 38 (KEY_L) */ + [0x2e] = 0x24, /* 46 => 36 via 36 (KEY_J) */ + [0x2f] = 0x28, /* 47 => 40 via 40 (KEY_APOSTROPHE) */ + [0x30] = 0x25, /* 48 => 37 via 37 (KEY_K) */ + [0x31] = 0x27, /* 49 => 39 via 39 (KEY_SEMICOLON) */ + [0x32] = 0x2b, /* 50 => 43 via 43 (KEY_BACKSLASH) */ + [0x33] = 0x33, /* 51 => 51 via 51 (KEY_COMMA) */ + [0x34] = 0x35, /* 52 => 53 via 53 (KEY_SLASH) */ + [0x35] = 0x31, /* 53 => 49 via 49 (KEY_N) */ + [0x36] = 0x32, /* 54 => 50 via 50 (KEY_M) */ + [0x37] = 0x34, /* 55 => 52 via 52 (KEY_DOT) */ + [0x38] = 0xf, /* 56 => 15 via 15 (KEY_TAB) */ + [0x39] = 0x39, /* 57 => 57 via 57 (KEY_SPACE) */ + [0x3a] = 0x29, /* 58 => 41 via 41 (KEY_GRAVE) */ + [0x3b] = 0xe, /* 59 => 14 via 14 (KEY_BACKSPACE) */ + [0x3d] = 0x1, /* 61 => 1 via 1 (KEY_ESC) */ + [0x3f] = 0x15b, /* 63 => 347 via 125 (KEY_LEFTMETA) */ + [0x40] = 0x2a, /* 64 => 42 via 42 (KEY_LEFTSHIFT) */ + [0x41] = 0x3a, /* 65 => 58 via 58 (KEY_CAPSLOCK) */ + [0x42] = 0x38, /* 66 => 56 via 56 (KEY_LEFTALT) */ + [0x43] = 0x1d, /* 67 => 29 via 29 (KEY_LEFTCTRL) */ + [0x44] = 0x36, /* 68 => 54 via 54 (KEY_RIGHTSHIFT) */ + [0x45] = 0x138, /* 69 => 312 via 100 (KEY_RIGHTALT) */ + [0x46] = 0x11d, /* 70 => 285 via 97 (KEY_RIGHTCTRL) */ + [0x47] = 0x15d, /* 71 => 349 via 127 (KEY_COMPOSE) */ + [0x48] = 0x103, /* 72 => 259 via 187 (KEY_F17) */ + [0x49] = 0x53, /* 73 => 83 via 83 (KEY_KPDOT) */ + [0x4b] = 0x37, /* 75 => 55 via 55 (KEY_KPASTERISK) */ + [0x4d] = 0x4e, /* 77 => 78 via 78 (KEY_KPPLUS) */ + [0x4f] = 0x7e, /* 79 => 126 via 121 (KEY_KPCOMMA) */ + [0x50] = 0x130, /* 80 => 304 via 115 (KEY_VOLUMEUP) */ + [0x51] = 0x12e, /* 81 => 302 via 114 (KEY_VOLUMEDOWN) */ + [0x52] = 0x120, /* 82 => 288 via 113 (KEY_MUTE) */ + [0x53] = 0x135, /* 83 => 309 via 98 (KEY_KPSLASH) */ + [0x54] = 0x11c, /* 84 => 284 via 96 (KEY_KPENTER) */ + [0x56] = 0x4a, /* 86 => 74 via 74 (KEY_KPMINUS) */ + [0x57] = 0x177, /* 87 => 375 via 188 (KEY_F18) */ + [0x58] = 0x104, /* 88 => 260 via 189 (KEY_F19) */ + [0x59] = 0x59, /* 89 => 89 via 117 (KEY_KPEQUAL) */ + [0x5a] = 0x52, /* 90 => 82 via 82 (KEY_KP0) */ + [0x5b] = 0x4f, /* 91 => 79 via 79 (KEY_KP1) */ + [0x5c] = 0x50, /* 92 => 80 via 80 (KEY_KP2) */ + [0x5d] = 0x51, /* 93 => 81 via 81 (KEY_KP3) */ + [0x5e] = 0x4b, /* 94 => 75 via 75 (KEY_KP4) */ + [0x5f] = 0x4c, /* 95 => 76 via 76 (KEY_KP5) */ + [0x60] = 0x4d, /* 96 => 77 via 77 (KEY_KP6) */ + [0x61] = 0x47, /* 97 => 71 via 71 (KEY_KP7) */ + [0x62] = 0x5a, /* 98 => 90 via 190 (KEY_F20) */ + [0x63] = 0x48, /* 99 => 72 via 72 (KEY_KP8) */ + [0x64] = 0x49, /* 100 => 73 via 73 (KEY_KP9) */ + [0x65] = 0x7d, /* 101 => 125 via 124 (KEY_YEN) */ + [0x67] = 0x5c, /* 103 => 92 via 95 (KEY_KPJPCOMMA) */ + [0x68] = 0x3f, /* 104 => 63 via 63 (KEY_F5) */ + [0x69] = 0x40, /* 105 => 64 via 64 (KEY_F6) */ + [0x6a] = 0x41, /* 106 => 65 via 65 (KEY_F7) */ + [0x6b] = 0x3d, /* 107 => 61 via 61 (KEY_F3) */ + [0x6c] = 0x42, /* 108 => 66 via 66 (KEY_F8) */ + [0x6d] = 0x43, /* 109 => 67 via 67 (KEY_F9) */ + [0x6f] = 0x57, /* 111 => 87 via 87 (KEY_F11) */ + [0x70] = 0x78, /* 112 => 120 via 90 (KEY_KATAKANA) */ + [0x71] = 0x5d, /* 113 => 93 via 183 (KEY_F13) */ + [0x72] = 0x55, /* 114 => 85 via 186 (KEY_F16) */ + [0x73] = 0x5e, /* 115 => 94 via 184 (KEY_F14) */ + [0x75] = 0x44, /* 117 => 68 via 68 (KEY_F10) */ + [0x77] = 0x58, /* 119 => 88 via 88 (KEY_F12) */ + [0x79] = 0x5f, /* 121 => 95 via 185 (KEY_F15) */ + [0x7b] = 0x147, /* 123 => 327 via 102 (KEY_HOME) */ + [0x7c] = 0x149, /* 124 => 329 via 104 (KEY_PAGEUP) */ + [0x7d] = 0x153, /* 125 => 339 via 111 (KEY_DELETE) */ + [0x7e] = 0x3e, /* 126 => 62 via 62 (KEY_F4) */ + [0x7f] = 0x14f, /* 127 => 335 via 107 (KEY_END) */ + [0x80] = 0x3c, /* 128 => 60 via 60 (KEY_F2) */ + [0x81] = 0x151, /* 129 => 337 via 109 (KEY_PAGEDOWN) */ + [0x82] = 0x3b, /* 130 => 59 via 59 (KEY_F1) */ + [0x83] = 0x14b, /* 131 => 331 via 105 (KEY_LEFT) */ + [0x84] = 0x14d, /* 132 => 333 via 106 (KEY_RIGHT) */ + [0x85] = 0x150, /* 133 => 336 via 108 (KEY_DOWN) */ + [0x86] = 0x148, /* 134 => 328 via 103 (KEY_UP) */ +}; diff --git a/src/vncdisplaykeymap_xorgxwin2xtkbd.c b/src/vncdisplaykeymap_xorgxwin2xtkbd.c new file mode 100644 index 0000000..7587a2c --- /dev/null +++ b/src/vncdisplaykeymap_xorgxwin2xtkbd.c @@ -0,0 +1,112 @@ +static const guint16 keymap_xorgxwin2xtkbd[] = { + [0x9] = 0x1, /* 9 => 1 via 1 (KEY_ESC) */ + [0xa] = 0x2, /* 10 => 2 via 2 (KEY_1) */ + [0xb] = 0x3, /* 11 => 3 via 3 (KEY_2) */ + [0xc] = 0x4, /* 12 => 4 via 4 (KEY_3) */ + [0xd] = 0x5, /* 13 => 5 via 5 (KEY_4) */ + [0xe] = 0x6, /* 14 => 6 via 6 (KEY_5) */ + [0xf] = 0x7, /* 15 => 7 via 7 (KEY_6) */ + [0x10] = 0x8, /* 16 => 8 via 8 (KEY_7) */ + [0x11] = 0x9, /* 17 => 9 via 9 (KEY_8) */ + [0x12] = 0xa, /* 18 => 10 via 10 (KEY_9) */ + [0x13] = 0xb, /* 19 => 11 via 11 (KEY_0) */ + [0x14] = 0xc, /* 20 => 12 via 12 (KEY_MINUS) */ + [0x15] = 0xd, /* 21 => 13 via 13 (KEY_EQUAL) */ + [0x16] = 0xe, /* 22 => 14 via 14 (KEY_BACKSPACE) */ + [0x17] = 0xf, /* 23 => 15 via 15 (KEY_TAB) */ + [0x18] = 0x10, /* 24 => 16 via 16 (KEY_Q) */ + [0x19] = 0x11, /* 25 => 17 via 17 (KEY_W) */ + [0x1a] = 0x12, /* 26 => 18 via 18 (KEY_E) */ + [0x1b] = 0x13, /* 27 => 19 via 19 (KEY_R) */ + [0x1c] = 0x14, /* 28 => 20 via 20 (KEY_T) */ + [0x1d] = 0x15, /* 29 => 21 via 21 (KEY_Y) */ + [0x1e] = 0x16, /* 30 => 22 via 22 (KEY_U) */ + [0x1f] = 0x17, /* 31 => 23 via 23 (KEY_I) */ + [0x20] = 0x18, /* 32 => 24 via 24 (KEY_O) */ + [0x21] = 0x19, /* 33 => 25 via 25 (KEY_P) */ + [0x22] = 0x1a, /* 34 => 26 via 26 (KEY_LEFTBRACE) */ + [0x23] = 0x1b, /* 35 => 27 via 27 (KEY_RIGHTBRACE) */ + [0x24] = 0x1c, /* 36 => 28 via 28 (KEY_ENTER) */ + [0x25] = 0x1d, /* 37 => 29 via 29 (KEY_LEFTCTRL) */ + [0x26] = 0x1e, /* 38 => 30 via 30 (KEY_A) */ + [0x27] = 0x1f, /* 39 => 31 via 31 (KEY_S) */ + [0x28] = 0x20, /* 40 => 32 via 32 (KEY_D) */ + [0x29] = 0x21, /* 41 => 33 via 33 (KEY_F) */ + [0x2a] = 0x22, /* 42 => 34 via 34 (KEY_G) */ + [0x2b] = 0x23, /* 43 => 35 via 35 (KEY_H) */ + [0x2c] = 0x24, /* 44 => 36 via 36 (KEY_J) */ + [0x2d] = 0x25, /* 45 => 37 via 37 (KEY_K) */ + [0x2e] = 0x26, /* 46 => 38 via 38 (KEY_L) */ + [0x2f] = 0x27, /* 47 => 39 via 39 (KEY_SEMICOLON) */ + [0x30] = 0x28, /* 48 => 40 via 40 (KEY_APOSTROPHE) */ + [0x31] = 0x29, /* 49 => 41 via 41 (KEY_GRAVE) */ + [0x32] = 0x2a, /* 50 => 42 via 42 (KEY_LEFTSHIFT) */ + [0x33] = 0x2b, /* 51 => 43 via 43 (KEY_BACKSLASH) */ + [0x34] = 0x2c, /* 52 => 44 via 44 (KEY_Z) */ + [0x35] = 0x2d, /* 53 => 45 via 45 (KEY_X) */ + [0x36] = 0x2e, /* 54 => 46 via 46 (KEY_C) */ + [0x37] = 0x2f, /* 55 => 47 via 47 (KEY_V) */ + [0x38] = 0x30, /* 56 => 48 via 48 (KEY_B) */ + [0x39] = 0x31, /* 57 => 49 via 49 (KEY_N) */ + [0x3a] = 0x32, /* 58 => 50 via 50 (KEY_M) */ + [0x3b] = 0x33, /* 59 => 51 via 51 (KEY_COMMA) */ + [0x3c] = 0x34, /* 60 => 52 via 52 (KEY_DOT) */ + [0x3d] = 0x35, /* 61 => 53 via 53 (KEY_SLASH) */ + [0x3e] = 0x36, /* 62 => 54 via 54 (KEY_RIGHTSHIFT) */ + [0x3f] = 0x37, /* 63 => 55 via 55 (KEY_KPASTERISK) */ + [0x40] = 0x38, /* 64 => 56 via 56 (KEY_LEFTALT) */ + [0x41] = 0x39, /* 65 => 57 via 57 (KEY_SPACE) */ + [0x42] = 0x3a, /* 66 => 58 via 58 (KEY_CAPSLOCK) */ + [0x43] = 0x3b, /* 67 => 59 via 59 (KEY_F1) */ + [0x44] = 0x3c, /* 68 => 60 via 60 (KEY_F2) */ + [0x45] = 0x3d, /* 69 => 61 via 61 (KEY_F3) */ + [0x46] = 0x3e, /* 70 => 62 via 62 (KEY_F4) */ + [0x47] = 0x3f, /* 71 => 63 via 63 (KEY_F5) */ + [0x48] = 0x40, /* 72 => 64 via 64 (KEY_F6) */ + [0x49] = 0x41, /* 73 => 65 via 65 (KEY_F7) */ + [0x4a] = 0x42, /* 74 => 66 via 66 (KEY_F8) */ + [0x4b] = 0x43, /* 75 => 67 via 67 (KEY_F9) */ + [0x4c] = 0x44, /* 76 => 68 via 68 (KEY_F10) */ + [0x4d] = 0x45, /* 77 => 69 via 69 (KEY_NUMLOCK) */ + [0x4e] = 0x46, /* 78 => 70 via 70 (KEY_SCROLLLOCK) */ + [0x4f] = 0x47, /* 79 => 71 via 71 (KEY_KP7) */ + [0x50] = 0x48, /* 80 => 72 via 72 (KEY_KP8) */ + [0x51] = 0x49, /* 81 => 73 via 73 (KEY_KP9) */ + [0x52] = 0x4a, /* 82 => 74 via 74 (KEY_KPMINUS) */ + [0x53] = 0x4b, /* 83 => 75 via 75 (KEY_KP4) */ + [0x54] = 0x4c, /* 84 => 76 via 76 (KEY_KP5) */ + [0x55] = 0x4d, /* 85 => 77 via 77 (KEY_KP6) */ + [0x56] = 0x4e, /* 86 => 78 via 78 (KEY_KPPLUS) */ + [0x57] = 0x4f, /* 87 => 79 via 79 (KEY_KP1) */ + [0x58] = 0x50, /* 88 => 80 via 80 (KEY_KP2) */ + [0x59] = 0x51, /* 89 => 81 via 81 (KEY_KP3) */ + [0x5a] = 0x52, /* 90 => 82 via 82 (KEY_KP0) */ + [0x5b] = 0x53, /* 91 => 83 via 83 (KEY_KPDOT) */ + [0x61] = 0x147, /* 97 => 327 via 102 (KEY_HOME) */ + [0x62] = 0x148, /* 98 => 328 via 103 (KEY_UP) */ + [0x63] = 0x149, /* 99 => 329 via 104 (KEY_PAGEUP) */ + [0x64] = 0x14b, /* 100 => 331 via 105 (KEY_LEFT) */ + [0x66] = 0x14d, /* 102 => 333 via 106 (KEY_RIGHT) */ + [0x67] = 0x14f, /* 103 => 335 via 107 (KEY_END) */ + [0x68] = 0x150, /* 104 => 336 via 108 (KEY_DOWN) */ + [0x69] = 0x151, /* 105 => 337 via 109 (KEY_PAGEDOWN) */ + [0x6a] = 0x152, /* 106 => 338 via 110 (KEY_INSERT) */ + [0x6b] = 0x153, /* 107 => 339 via 111 (KEY_DELETE) */ + [0x6c] = 0x11c, /* 108 => 284 via 96 (KEY_KPENTER) */ + [0x6d] = 0x11d, /* 109 => 285 via 97 (KEY_RIGHTCTRL) */ + [0x6e] = 0x146, /* 110 => 326 via 119 (KEY_PAUSE) */ + [0x6f] = 0x54, /* 111 => 84 via 99 (KEY_SYSRQ) */ + [0x70] = 0x135, /* 112 => 309 via 98 (KEY_KPSLASH) */ + [0x71] = 0x138, /* 113 => 312 via 100 (KEY_RIGHTALT) */ + [0x73] = 0x15b, /* 115 => 347 via 125 (KEY_LEFTMETA) */ + [0x74] = 0x15c, /* 116 => 348 via 126 (KEY_RIGHTMETA) */ + [0x75] = 0x15d, /* 117 => 349 via 127 (KEY_COMPOSE) */ + [0x76] = 0x5d, /* 118 => 93 via 183 (KEY_F13) */ + [0x77] = 0x5e, /* 119 => 94 via 184 (KEY_F14) */ + [0x78] = 0x5f, /* 120 => 95 via 185 (KEY_F15) */ + [0x79] = 0x55, /* 121 => 85 via 186 (KEY_F16) */ + [0x7a] = 0x103, /* 122 => 259 via 187 (KEY_F17) */ + [0x7e] = 0x59, /* 126 => 89 via 117 (KEY_KPEQUAL) */ + [0x85] = 0x7d, /* 133 => 125 via 124 (KEY_YEN) */ + [0xd0] = 0x70, /* 208 => 112 via 93 (KEY_KATAKANAHIRAGANA) */ +}; diff --git a/src/win-usb-clerk.h b/src/win-usb-clerk.h new file mode 100644 index 0000000..a17980d --- /dev/null +++ b/src/win-usb-clerk.h @@ -0,0 +1,36 @@ +#ifndef _H_USBCLERK +#define _H_USBCLERK + +#include <windows.h> + +#define USB_CLERK_PIPE_NAME TEXT("\\\\.\\pipe\\usbclerkpipe") +#define USB_CLERK_MAGIC 0xDADAu +#define USB_CLERK_VERSION 0x0003u + +typedef struct USBClerkHeader { + UINT16 magic; + UINT16 version; + UINT16 type; + UINT16 size; +} USBClerkHeader; + +enum { + USB_CLERK_DRIVER_INSTALL = 1, + USB_CLERK_DRIVER_REMOVE, + USB_CLERK_REPLY, + USB_CLERK_DRIVER_SESSION_INSTALL, + USB_CLERK_END_MESSAGE, +}; + +typedef struct USBClerkDriverOp { + USBClerkHeader hdr; + UINT16 vid; + UINT16 pid; +} USBClerkDriverOp; + +typedef struct USBClerkReply { + USBClerkHeader hdr; + UINT32 status; +} USBClerkReply; + +#endif diff --git a/src/win-usb-dev.c b/src/win-usb-dev.c new file mode 100644 index 0000000..1cf9f21 --- /dev/null +++ b/src/win-usb-dev.c @@ -0,0 +1,583 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Arnon Gilboa <agilboa@redhat.com> + Uri Lublin <uril@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <windows.h> +#include <libusb.h> +#include "win-usb-dev.h" +#include "spice-marshal.h" +#include "spice-util.h" +#include "usbutil.h" + +#define G_UDEV_CLIENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), G_UDEV_TYPE_CLIENT, GUdevClientPrivate)) + +enum { + PROP_0, + PROP_REDIRECTING +}; + +struct _GUdevClientPrivate { + libusb_context *ctx; + GList *udev_list; + HWND hwnd; + gboolean redirecting; +}; + +#define G_UDEV_CLIENT_WINCLASS_NAME TEXT("G_UDEV_CLIENT") + +static void g_udev_client_initable_iface_init(GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE(GUdevClient, g_udev_client, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, g_udev_client_initable_iface_init)); + + +typedef struct _GUdevDeviceInfo GUdevDeviceInfo; + +struct _GUdevDeviceInfo { + guint16 bus; + guint16 addr; + guint16 vid; + guint16 pid; + guint16 class; + gchar sclass[4]; + gchar sbus[4]; + gchar saddr[4]; + gchar svid[8]; + gchar spid[8]; +}; + +struct _GUdevDevicePrivate +{ + /* FixMe: move above fields to this structure and access them directly */ + GUdevDeviceInfo *udevinfo; +}; + +G_DEFINE_TYPE(GUdevDevice, g_udev_device, G_TYPE_OBJECT) + + +enum +{ + UEVENT_SIGNAL, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = { 0, }; +static GUdevClient *singleton = NULL; + +static GUdevDevice *g_udev_device_new(GUdevDeviceInfo *udevinfo); +static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); +static gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo *udevinfo); + +//uncomment to debug gudev device lists. +//#define DEBUG_GUDEV_DEVICE_LISTS + +#ifdef DEBUG_GUDEV_DEVICE_LISTS +static void g_udev_device_print_list(GList *l, const gchar *msg); +#else +static void g_udev_device_print_list(GList *l, const gchar *msg) {} +#endif +static void g_udev_device_print(GUdevDevice *udev, const gchar *msg); + +static gboolean g_udev_skip_search(GUdevDevice *udev); + +GQuark g_udev_client_error_quark(void) +{ + return g_quark_from_static_string("win-gudev-client-error-quark"); +} + +GUdevClient *g_udev_client_new(const gchar* const *subsystems) +{ + if (!singleton) { + singleton = g_initable_new(G_UDEV_TYPE_CLIENT, NULL, NULL, NULL); + return singleton; + } else { + return g_object_ref(singleton); + } +} + + +/* + * devs [in,out] an empty devs list in, full devs list out + * Returns: number-of-devices, or a negative value on error. + */ +static ssize_t +g_udev_client_list_devices(GUdevClient *self, GList **devs, + GError **err, const gchar *name) +{ + gssize rc; + libusb_device **lusb_list, **dev; + GUdevClientPrivate *priv; + GUdevDeviceInfo *udevinfo; + GUdevDevice *udevice; + ssize_t n; + + g_return_val_if_fail(G_UDEV_IS_CLIENT(self), -1); + g_return_val_if_fail(devs != NULL, -2); + + priv = self->priv; + + g_return_val_if_fail(self->priv->ctx != NULL, -3); + + rc = libusb_get_device_list(priv->ctx, &lusb_list); + if (rc < 0) { + const char *errstr = spice_usbutil_libusb_strerror(rc); + g_warning("%s: libusb_get_device_list failed", name); + g_set_error(err, G_UDEV_CLIENT_ERROR, G_UDEV_CLIENT_LIBUSB_FAILED, + "%s: Error getting device list from libusb: %s [%"G_GSSIZE_FORMAT"]", + name, errstr, rc); + return -4; + } + + n = 0; + for (dev = lusb_list; *dev; dev++) { + udevinfo = g_new0(GUdevDeviceInfo, 1); + get_usb_dev_info(*dev, udevinfo); + udevice = g_udev_device_new(udevinfo); + if (g_udev_skip_search(udevice)) { + g_object_unref(udevice); + continue; + } + *devs = g_list_prepend(*devs, udevice); + n++; + } + libusb_free_device_list(lusb_list, 1); + + return n; +} + +static void g_udev_client_free_device_list(GList **devs) +{ + g_return_if_fail(devs != NULL); + if (*devs) { + g_list_free_full(*devs, g_object_unref); + *devs = NULL; + } +} + + +static gboolean +g_udev_client_initable_init(GInitable *initable, GCancellable *cancellable, + GError **err) +{ + GUdevClient *self; + GUdevClientPrivate *priv; + WNDCLASS wcls; + int rc; + + g_return_val_if_fail(G_UDEV_IS_CLIENT(initable), FALSE); + g_return_val_if_fail(cancellable == NULL, FALSE); + + self = G_UDEV_CLIENT(initable); + priv = self->priv; + + rc = libusb_init(&priv->ctx); + if (rc < 0) { + const char *errstr = spice_usbutil_libusb_strerror(rc); + g_warning("Error initializing USB support: %s [%i]", errstr, rc); + g_set_error(err, G_UDEV_CLIENT_ERROR, G_UDEV_CLIENT_LIBUSB_FAILED, + "Error initializing USB support: %s [%i]", errstr, rc); + return FALSE; + } + + /* get initial device list */ + if (g_udev_client_list_devices(self, &priv->udev_list, err, __FUNCTION__) < 0) { + goto g_udev_client_init_failed; + } + + g_udev_device_print_list(priv->udev_list, "init: first list is: "); + + /* create a hidden window */ + memset(&wcls, 0, sizeof(wcls)); + wcls.lpfnWndProc = wnd_proc; + wcls.lpszClassName = G_UDEV_CLIENT_WINCLASS_NAME; + if (!RegisterClass(&wcls)) { + DWORD e = GetLastError(); + g_warning("RegisterClass failed , %ld", (long)e); + g_set_error(err, G_UDEV_CLIENT_ERROR, G_UDEV_CLIENT_WINAPI_FAILED, + "RegisterClass failed: %ld", (long)e); + goto g_udev_client_init_failed; + } + priv->hwnd = CreateWindow(G_UDEV_CLIENT_WINCLASS_NAME, + NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + if (!priv->hwnd) { + DWORD e = GetLastError(); + g_warning("CreateWindow failed: %ld", (long)e); + g_set_error(err, G_UDEV_CLIENT_ERROR, G_UDEV_CLIENT_LIBUSB_FAILED, + "CreateWindow failed: %ld", (long)e); + goto g_udev_client_init_failed_unreg; + } + + return TRUE; + + g_udev_client_init_failed_unreg: + UnregisterClass(G_UDEV_CLIENT_WINCLASS_NAME, NULL); + g_udev_client_init_failed: + libusb_exit(priv->ctx); + priv->ctx = NULL; + + return FALSE; +} + +static void g_udev_client_initable_iface_init(GInitableIface *iface) +{ + iface->init = g_udev_client_initable_init; +} + +GList *g_udev_client_query_by_subsystem(GUdevClient *self, const gchar *subsystem) +{ + GList *l = g_list_copy(self->priv->udev_list); + g_list_foreach(l, (GFunc)g_object_ref, NULL); + return l; +} + +static void g_udev_client_init(GUdevClient *self) +{ + self->priv = G_UDEV_CLIENT_GET_PRIVATE(self); +} + +static void g_udev_client_finalize(GObject *gobject) +{ + GUdevClient *self = G_UDEV_CLIENT(gobject); + GUdevClientPrivate *priv = self->priv; + + singleton = NULL; + DestroyWindow(priv->hwnd); + UnregisterClass(G_UDEV_CLIENT_WINCLASS_NAME, NULL); + g_udev_client_free_device_list(&priv->udev_list); + + /* free libusb context initializing by libusb_init() */ + g_warn_if_fail(priv->ctx != NULL); + libusb_exit(priv->ctx); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(g_udev_client_parent_class)->finalize) + G_OBJECT_CLASS(g_udev_client_parent_class)->finalize(gobject); +} + +static void g_udev_client_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GUdevClient *self = G_UDEV_CLIENT(gobject); + GUdevClientPrivate *priv = self->priv; + + switch (prop_id) { + case PROP_REDIRECTING: + g_value_set_boolean(value, priv->redirecting); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void handle_dev_change(GUdevClient *self); + +static void g_udev_client_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GUdevClient *self = G_UDEV_CLIENT(gobject); + GUdevClientPrivate *priv = self->priv; + gboolean old_val; + + switch (prop_id) { + case PROP_REDIRECTING: + old_val = priv->redirecting; + priv->redirecting = g_value_get_boolean(value); + if (old_val && !priv->redirecting) { + /* This is a redirection completion case. + Inject hotplug event in case we missed device changes + during redirection processing. */ + handle_dev_change(self); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void g_udev_client_class_init(GUdevClientClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GParamSpec *pspec; + + gobject_class->finalize = g_udev_client_finalize; + gobject_class->get_property = g_udev_client_get_property; + gobject_class->set_property = g_udev_client_set_property; + + signals[UEVENT_SIGNAL] = + g_signal_new("uevent", + G_OBJECT_CLASS_TYPE(klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(GUdevClientClass, uevent), + NULL, NULL, + g_cclosure_user_marshal_VOID__BOXED_BOXED, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_UDEV_TYPE_DEVICE); + + /** + * GUdevClient::redirecting: + * + * This property indicates when a redirection operation + * is in progress on a device. It's set back to FALSE + * once the device is fully redirected to the guest. + */ + pspec = g_param_spec_boolean("redirecting", "Redirecting", + "USB redirection operation is in progress", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_property(gobject_class, PROP_REDIRECTING, pspec); + + g_type_class_add_private(klass, sizeof(GUdevClientPrivate)); +} + +static gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo *udevinfo) +{ + struct libusb_device_descriptor desc; + + g_return_val_if_fail(dev, FALSE); + g_return_val_if_fail(udevinfo, FALSE); + + if (libusb_get_device_descriptor(dev, &desc) < 0) { + g_warning("cannot get device descriptor %p", dev); + return FALSE; + } + + udevinfo->bus = libusb_get_bus_number(dev); + udevinfo->addr = libusb_get_device_address(dev); + udevinfo->class = desc.bDeviceClass; + udevinfo->vid = desc.idVendor; + udevinfo->pid = desc.idProduct; + snprintf(udevinfo->sclass, sizeof(udevinfo->sclass), "%d", udevinfo->class); + snprintf(udevinfo->sbus, sizeof(udevinfo->sbus), "%d", udevinfo->bus); + snprintf(udevinfo->saddr, sizeof(udevinfo->saddr), "%d", udevinfo->addr); + snprintf(udevinfo->svid, sizeof(udevinfo->svid), "%d", udevinfo->vid); + snprintf(udevinfo->spid, sizeof(udevinfo->spid), "%d", udevinfo->pid); + return TRUE; +} + +/* Only vid:pid are compared */ +static gint gudev_devices_differ(gconstpointer a, gconstpointer b) +{ + GUdevDeviceInfo *ai, *bi; + gboolean same_vid; + gboolean same_pid; + + ai = G_UDEV_DEVICE(a)->priv->udevinfo; + bi = G_UDEV_DEVICE(b)->priv->udevinfo; + + same_vid = (ai->vid == bi->vid); + same_pid = (ai->pid == bi->pid); + + return (same_pid && same_vid) ? 0 : -1; +} + +static void notify_dev_state_change(GUdevClient *self, + GList *old_list, + GList *new_list, + const gchar *action) +{ + GList *dev; + + for (dev = g_list_first(old_list); dev != NULL; dev = g_list_next(dev)) { + if (g_list_find_custom(new_list, dev->data, gudev_devices_differ) == NULL) { + /* Found a device that changed its state */ + g_udev_device_print(dev->data, action); + g_signal_emit(self, signals[UEVENT_SIGNAL], 0, action, dev->data); + } + } +} + +static void handle_dev_change(GUdevClient *self) +{ + GUdevClientPrivate *priv = self->priv; + GError *err = NULL; + GList *now_devs = NULL; + + if (priv->redirecting == TRUE) { + /* On Windows, querying USB device list may return inconsistent results + if performed in parallel to redirection flow. + A simulated hotplug event will be injected after redirection + completion in order to process real device list changes that may + had taken place during redirection process. */ + return; + } + + if(g_udev_client_list_devices(self, &now_devs, &err, __FUNCTION__) < 0) { + g_warning("could not retrieve device list"); + return; + } + + g_udev_device_print_list(now_devs, "handle_dev_change: current list:"); + g_udev_device_print_list(priv->udev_list, "handle_dev_change: previous list:"); + + /* Unregister devices that are not present anymore */ + notify_dev_state_change(self, priv->udev_list, now_devs, "remove"); + + /* Register newly inserted devices */ + notify_dev_state_change(self, now_devs, priv->udev_list, "add"); + + /* keep most recent info: free previous list, and keep current list */ + g_udev_client_free_device_list(&priv->udev_list); + priv->udev_list = now_devs; +} + +static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + /* Only DBT_DEVNODES_CHANGED recieved */ + if (message == WM_DEVICECHANGE) { + handle_dev_change(singleton); + } + return DefWindowProc(hwnd, message, wparam, lparam); +} + +/*** GUdevDevice ***/ + +static void g_udev_device_finalize(GObject *object) +{ + GUdevDevice *device = G_UDEV_DEVICE(object); + + g_free(device->priv->udevinfo); + if (G_OBJECT_CLASS(g_udev_device_parent_class)->finalize != NULL) + (* G_OBJECT_CLASS(g_udev_device_parent_class)->finalize)(object); +} + +static void g_udev_device_class_init(GUdevDeviceClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = g_udev_device_finalize; + g_type_class_add_private (klass, sizeof(GUdevDevicePrivate)); +} + +static void g_udev_device_init(GUdevDevice *device) +{ + device->priv = G_TYPE_INSTANCE_GET_PRIVATE(device, G_UDEV_TYPE_DEVICE, GUdevDevicePrivate); +} + +static GUdevDevice *g_udev_device_new(GUdevDeviceInfo *udevinfo) +{ + GUdevDevice *device; + + g_return_val_if_fail(udevinfo != NULL, NULL); + + device = G_UDEV_DEVICE(g_object_new(G_UDEV_TYPE_DEVICE, NULL)); + device->priv->udevinfo = udevinfo; + return device; +} + +const gchar *g_udev_device_get_property(GUdevDevice *udev, const gchar *property) +{ + GUdevDeviceInfo* udevinfo; + + g_return_val_if_fail(G_UDEV_DEVICE(udev), NULL); + g_return_val_if_fail(property != NULL, NULL); + + udevinfo = udev->priv->udevinfo; + g_return_val_if_fail(udevinfo != NULL, NULL); + + if (g_strcmp0(property, "BUSNUM") == 0) { + return udevinfo->sbus; + } else if (g_strcmp0(property, "DEVNUM") == 0) { + return udevinfo->saddr; + } else if (g_strcmp0(property, "DEVTYPE") == 0) { + return "usb_device"; + } else if (g_strcmp0(property, "VID") == 0) { + return udevinfo->svid; + } else if (g_strcmp0(property, "PID") == 0) { + return udevinfo->spid; + } + + g_warn_if_reached(); + return NULL; +} + +const gchar *g_udev_device_get_sysfs_attr(GUdevDevice *udev, const gchar *attr) +{ + GUdevDeviceInfo* udevinfo; + + g_return_val_if_fail(G_UDEV_DEVICE(udev), NULL); + g_return_val_if_fail(attr != NULL, NULL); + + udevinfo = udev->priv->udevinfo; + g_return_val_if_fail(udevinfo != NULL, NULL); + + + if (g_strcmp0(attr, "bDeviceClass") == 0) { + return udevinfo->sclass; + } + g_warn_if_reached(); + return NULL; +} + +#ifdef DEBUG_GUDEV_DEVICE_LISTS +static void g_udev_device_print_list(GList *l, const gchar *msg) +{ + GList *it; + + for (it = g_list_first(l); it != NULL; it=g_list_next(it)) { + g_udev_device_print(it->data, msg); + } +} +#endif + +static void g_udev_device_print(GUdevDevice *udev, const gchar *msg) +{ + GUdevDeviceInfo* udevinfo; + + g_return_if_fail(G_UDEV_DEVICE(udev)); + + udevinfo = udev->priv->udevinfo; + g_return_if_fail(udevinfo != NULL); + + SPICE_DEBUG("%s: %d.%d 0x%04x:0x%04x class %d", msg, + udevinfo->bus, udevinfo->addr, + udevinfo->vid, udevinfo->pid, udevinfo->class); +} + +static gboolean g_udev_skip_search(GUdevDevice *udev) +{ + GUdevDeviceInfo* udevinfo; + gboolean skip; + + g_return_val_if_fail(G_UDEV_DEVICE(udev), FALSE); + + udevinfo = udev->priv->udevinfo; + g_return_val_if_fail(udevinfo != NULL, FALSE); + + skip = ((udevinfo->addr == 0xff) || /* root hub (HCD) */ +#if defined(LIBUSBX_API_VERSION) && (LIBUSBX_API_VERSION >= 0x010000FF) + (udevinfo->addr == 1) || /* root hub addr for libusbx >= 1.0.13 */ +#endif + (udevinfo->class == LIBUSB_CLASS_HUB) || /* hub*/ + (udevinfo->addr == 0)); /* bad address */ + return skip; +} diff --git a/src/win-usb-dev.h b/src/win-usb-dev.h new file mode 100644 index 0000000..b5c4fce --- /dev/null +++ b/src/win-usb-dev.h @@ -0,0 +1,110 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Arnon Gilboa <agilboa@redhat.com> + Uri Lublin <uril@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __WIN_USB_DEV_H__ +#define __WIN_USB_DEV_H__ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +/* GUdevDevice */ + +#define G_UDEV_TYPE_DEVICE (g_udev_device_get_type()) +#define G_UDEV_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), G_UDEV_TYPE_DEVICE, GUdevDevice)) +#define G_UDEV_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) +#define G_UDEV_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_DEVICE)) +#define G_UDEV_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), G_UDEV_TYPE_DEVICE)) +#define G_UDEV_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) + +typedef struct _GUdevDevice GUdevDevice; +typedef struct _GUdevDeviceClass GUdevDeviceClass; +typedef struct _GUdevDevicePrivate GUdevDevicePrivate; + +struct _GUdevDevice +{ + GObject parent; + GUdevDevicePrivate *priv; +}; + +struct _GUdevDeviceClass +{ + GObjectClass parent_class; +}; + +/* GUdevClient */ + +#define G_UDEV_TYPE_CLIENT (g_udev_client_get_type()) +#define G_UDEV_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), G_UDEV_TYPE_CLIENT, GUdevClient)) +#define G_UDEV_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_CLIENT, GUdevClientClass)) +#define G_UDEV_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), G_UDEV_TYPE_CLIENT)) +#define G_UDEV_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), G_UDEV_TYPE_CLIENT)) +#define G_UDEV_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), G_UDEV_TYPE_CLIENT, GUdevClientClass)) + +typedef struct _GUdevClient GUdevClient; +typedef struct _GUdevClientClass GUdevClientClass; +typedef struct _GUdevClientPrivate GUdevClientPrivate; + +struct _GUdevClient +{ + GObject parent; + + GUdevClientPrivate *priv; +}; + +struct _GUdevClientClass +{ + GObjectClass parent_class; + + /* signals */ + void (*uevent)(GUdevClient *client, const gchar *action, GUdevDevice *device); +}; + +GType g_udev_client_get_type(void) G_GNUC_CONST; +GUdevClient *g_udev_client_new(const gchar* const *subsystems); +GList *g_udev_client_query_by_subsystem(GUdevClient *client, const gchar *subsystem); + +GType g_udev_device_get_type(void) G_GNUC_CONST; +const gchar *g_udev_device_get_property(GUdevDevice *udev, const gchar *property); +const gchar *g_udev_device_get_sysfs_attr(GUdevDevice *udev, const gchar *attr); + +GQuark g_udev_client_error_quark(void); +#define G_UDEV_CLIENT_ERROR g_udev_client_error_quark() + +/** + * GUdevClientError: + * @G_UDEV_CLIENT_ERROR_FAILED: generic error code + * @G_UDEV_CLIENT_LIBUSB_FAILED: a libusb call failed + * @G_UDEV_CLIENT_WINAPI_FAILED: a winapi call failed + * + * Error codes returned by spice-client API. + */ +typedef enum +{ + G_UDEV_CLIENT_ERROR_FAILED = 1, + G_UDEV_CLIENT_LIBUSB_FAILED, + G_UDEV_CLIENT_WINAPI_FAILED +} GUdevClientError; + + +G_END_DECLS + +#endif /* __WIN_USB_DEV_H__ */ diff --git a/src/win-usb-driver-install.c b/src/win-usb-driver-install.c new file mode 100644 index 0000000..a72fcb8 --- /dev/null +++ b/src/win-usb-driver-install.c @@ -0,0 +1,421 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Uri Lublin <uril@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Some notes: + * Each installer (instance) opens a named-pipe to talk with win-usb-clerk. + * Each installer (instance) requests driver installation for a single device. + */ + +#include "config.h" + +#include <windows.h> +#include <gio/gio.h> +#include <gio/gwin32inputstream.h> +#include <gio/gwin32outputstream.h> +#include "spice-util.h" +#include "win-usb-clerk.h" +#include "win-usb-driver-install.h" +#include "usb-device-manager-priv.h" + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_WIN_USB_DRIVER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverPrivate)) + +struct _SpiceWinUsbDriverPrivate { + USBClerkReply reply; + GTask *task; + HANDLE handle; + SpiceUsbDevice *device; +}; + + +static void spice_win_usb_driver_initable_iface_init(GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE(SpiceWinUsbDriver, spice_win_usb_driver, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, spice_win_usb_driver_initable_iface_init)); + +static void spice_win_usb_driver_init(SpiceWinUsbDriver *self) +{ + self->priv = SPICE_WIN_USB_DRIVER_GET_PRIVATE(self); +} + +static gboolean spice_win_usb_driver_initable_init(GInitable *initable, + GCancellable *cancellable, + GError **err) +{ + SpiceWinUsbDriver *self = SPICE_WIN_USB_DRIVER(initable); + SpiceWinUsbDriverPrivate *priv = self->priv; + + SPICE_DEBUG("win-usb-driver-install: connecting to usbclerk named pipe"); + priv->handle = CreateFile(USB_CLERK_PIPE_NAME, + GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + if (priv->handle == INVALID_HANDLE_VALUE) { + DWORD errval = GetLastError(); + gchar *errstr = g_win32_error_message(errval); + g_set_error(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_USB_SERVICE, + "Failed to create service named pipe (%lu) %s", errval, errstr); + g_free(errstr); + return FALSE; + } + + return TRUE; +} + +static void spice_win_usb_driver_finalize(GObject *gobject) +{ + SpiceWinUsbDriver *self = SPICE_WIN_USB_DRIVER(gobject); + SpiceWinUsbDriverPrivate *priv = self->priv; + + if (priv->handle) + CloseHandle(priv->handle); + + g_clear_object(&priv->task); + + if (G_OBJECT_CLASS(spice_win_usb_driver_parent_class)->finalize) + G_OBJECT_CLASS(spice_win_usb_driver_parent_class)->finalize(gobject); +} + +static void spice_win_usb_driver_class_init(SpiceWinUsbDriverClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = spice_win_usb_driver_finalize; + + g_type_class_add_private(klass, sizeof(SpiceWinUsbDriverPrivate)); +} + +static void spice_win_usb_driver_initable_iface_init(GInitableIface *iface) +{ + iface->init = spice_win_usb_driver_initable_init; +} + +/* ------------------------------------------------------------------ */ +/* callbacks */ + +static +void win_usb_driver_handle_reply_cb(GObject *gobject, + GAsyncResult *read_res, + gpointer user_data) +{ + SpiceWinUsbDriver *self; + SpiceWinUsbDriverPrivate *priv; + + GInputStream *istream; + GError *err = NULL; + gssize bytes; + + g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(user_data)); + self = SPICE_WIN_USB_DRIVER(user_data); + priv = self->priv; + istream = G_INPUT_STREAM(gobject); + + bytes = g_input_stream_read_finish(istream, read_res, &err); + + SPICE_DEBUG("Finished reading reply-msg from usbclerk: bytes=%ld " + "err_exist?=%d", (long)bytes, err!=NULL); + + g_warn_if_fail(g_input_stream_close(istream, NULL, NULL)); + g_clear_object(&istream); + + if (err) { + g_warning("failed to read reply from usbclerk (%s)", err->message); + g_task_return_error(priv->task, err); + goto failed_reply; + } + + if (bytes == 0) { + g_warning("unexpected EOF from usbclerk"); + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_FAILED, + "unexpected EOF from usbclerk"); + goto failed_reply; + } + + if (bytes != sizeof(priv->reply)) { + g_warning("usbclerk size mismatch: read %"G_GSSIZE_FORMAT" bytes,expected " + "%"G_GSSIZE_FORMAT" (header %"G_GSSIZE_FORMAT", size in header %d)", + bytes, sizeof(priv->reply), sizeof(priv->reply.hdr), priv->reply.hdr.size); + /* For now just warn, do not fail */ + } + + if (priv->reply.hdr.magic != USB_CLERK_MAGIC) { + g_warning("usbclerk magic mismatch: mine=0x%04x server=0x%04x", + USB_CLERK_MAGIC, priv->reply.hdr.magic); + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, + "usbclerk magic mismatch"); + goto failed_reply; + } + + if (priv->reply.hdr.version != USB_CLERK_VERSION) { + g_warning("usbclerk version mismatch: mine=0x%04x server=0x%04x", + USB_CLERK_VERSION, priv->reply.hdr.version); + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, + "usbclerk version mismatch"); + } + + if (priv->reply.hdr.type != USB_CLERK_REPLY) { + g_warning("usbclerk message with unexpected type %d", + priv->reply.hdr.type); + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, + "usbclerk message with unexpected type"); + goto failed_reply; + } + + if (priv->reply.hdr.size != bytes) { + g_warning("usbclerk message size mismatch: read %"G_GSSIZE_FORMAT" bytes hdr.size=%d", + bytes, priv->reply.hdr.size); + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, + "usbclerk message with unexpected size"); + goto failed_reply; + } + + if (priv->reply.status == 0) { + g_task_return_new_error(priv->task, + SPICE_WIN_USB_DRIVER_ERROR, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, + "usbclerk error reply"); + goto failed_reply; + } + + g_task_return_boolean (priv->task, TRUE); + + failed_reply: + g_clear_object(&priv->task); +} + +/* ------------------------------------------------------------------ */ +/* helper functions */ + +static +gboolean spice_win_usb_driver_send_request(SpiceWinUsbDriver *self, guint16 op, + guint16 vid, guint16 pid, GError **err) +{ + USBClerkDriverOp req; + GOutputStream *ostream; + SpiceWinUsbDriverPrivate *priv; + gsize bytes; + gboolean ret; + + SPICE_DEBUG("sending a request to usbclerk service (op=%d vid=0x%04x pid=0x%04x", + op, vid, pid); + + g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), FALSE); + priv = self->priv; + + memset(&req, 0, sizeof(req)); + req.hdr.magic = USB_CLERK_MAGIC; + req.hdr.version = USB_CLERK_VERSION; + req.hdr.type = op; + req.hdr.size = sizeof(req); + req.vid = vid; + req.pid = pid; + + ostream = g_win32_output_stream_new(priv->handle, FALSE); + + ret = g_output_stream_write_all(ostream, &req, sizeof(req), &bytes, NULL, err); + g_warn_if_fail(g_output_stream_close(ostream, NULL, NULL)); + g_object_unref(ostream); + SPICE_DEBUG("write_all request returned %d written bytes %"G_GSIZE_FORMAT + " expecting %"G_GSIZE_FORMAT, + ret, bytes, sizeof(req)); + return ret; +} + +static +void spice_win_usb_driver_read_reply_async(SpiceWinUsbDriver *self) +{ + SpiceWinUsbDriverPrivate *priv; + GInputStream *istream; + + g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(self)); + priv = self->priv; + + SPICE_DEBUG("waiting for a reply from usbclerk"); + + istream = g_win32_input_stream_new(priv->handle, FALSE); + + g_input_stream_read_async(istream, &priv->reply, sizeof(priv->reply), + G_PRIORITY_DEFAULT, + g_task_get_cancellable(priv->task), + win_usb_driver_handle_reply_cb, self); +} + + +/* ------------------------------------------------------------------ */ +/* private api */ + + +G_GNUC_INTERNAL +SpiceWinUsbDriver *spice_win_usb_driver_new(GError **err) +{ + GObject *self; + + g_return_val_if_fail(err == NULL || *err == NULL, FALSE); + + self = g_initable_new(SPICE_TYPE_WIN_USB_DRIVER, NULL, err, NULL); + + return SPICE_WIN_USB_DRIVER(self); +} + +static +void spice_win_usb_driver_op(SpiceWinUsbDriver *self, + SpiceUsbDevice *device, + guint16 op_type, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + guint16 vid, pid; + GError *err = NULL; + GTask *task; + SpiceWinUsbDriverPrivate *priv; + + g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(self)); + g_return_if_fail(device != NULL); + + priv = self->priv; + + task = g_task_new(self, cancellable, callback, user_data); + + if (priv->task) { /* allow one install/uninstall request at a time */ + g_warning("Another request exists -- try later"); + g_task_return_new_error(task, + SPICE_WIN_USB_DRIVER_ERROR, SPICE_WIN_USB_DRIVER_ERROR_FAILED, + "Another request exists -- try later"); + goto failed_request; + } + + + vid = spice_usb_device_get_vid(device); + pid = spice_usb_device_get_pid(device); + + if (!spice_win_usb_driver_send_request(self, op_type, + vid, pid, &err)) { + g_warning("failed to send a request to usbclerk %s", err->message); + g_task_return_error(task, err); + goto failed_request; + } + + /* set up for async read */ + priv->task = task; + priv->device = device; + + spice_win_usb_driver_read_reply_async(self); + + return; + + failed_request: + g_clear_object(&task); +} + +/* + * Returns: currently returns 0 (failure) and 1 (success) + * possibly later we'll add error-codes + */ +static gboolean +spice_win_usb_driver_op_finish(SpiceWinUsbDriver *self, + GAsyncResult *res, GError **err) +{ + GTask *task = G_TASK(res); + + g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), 0); + g_return_val_if_fail(g_task_is_valid(task, self), FALSE); + + return g_task_propagate_boolean(task, err); +} + +/** + * spice_win_usb_driver_install_async: + * Start libusb driver installation for @device + * + * A new NamedPipe is created for each request. + * + * Returns: TRUE if a request was sent to usbclerk + * FALSE upon failure to send a request. + */ +G_GNUC_INTERNAL +void spice_win_usb_driver_install_async(SpiceWinUsbDriver *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SPICE_DEBUG("Win usb driver installation started"); + + spice_win_usb_driver_op(self, device, USB_CLERK_DRIVER_SESSION_INSTALL, + cancellable, callback, user_data); +} + +G_GNUC_INTERNAL +void spice_win_usb_driver_uninstall_async(SpiceWinUsbDriver *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SPICE_DEBUG("Win usb driver uninstall operation started"); + + spice_win_usb_driver_op(self, device, USB_CLERK_DRIVER_REMOVE, cancellable, + callback, user_data); +} + +G_GNUC_INTERNAL +gboolean spice_win_usb_driver_install_finish(SpiceWinUsbDriver *self, + GAsyncResult *res, GError **err) +{ + return spice_win_usb_driver_op_finish(self, res, err); +} + +G_GNUC_INTERNAL +gboolean spice_win_usb_driver_uninstall_finish(SpiceWinUsbDriver *self, + GAsyncResult *res, GError **err) +{ + return spice_win_usb_driver_op_finish(self, res, err); +} + +G_GNUC_INTERNAL +SpiceUsbDevice *spice_win_usb_driver_get_device(SpiceWinUsbDriver *self) +{ + g_return_val_if_fail(SPICE_IS_WIN_USB_DRIVER(self), 0); + + return self->priv->device; +} + +GQuark spice_win_usb_driver_error_quark(void) +{ + return g_quark_from_static_string("spice-win-usb-driver-error-quark"); +} diff --git a/src/win-usb-driver-install.h b/src/win-usb-driver-install.h new file mode 100644 index 0000000..f9afedc --- /dev/null +++ b/src/win-usb-driver-install.h @@ -0,0 +1,106 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + Red Hat Authors: + Uri Lublin <uril@redhat.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef SPICE_WIN_USB_DRIVER_H +#define SPICE_WIN_USB_DRIVER_H + +#include "usb-device-manager.h" + +G_BEGIN_DECLS + +GQuark win_usb_driver_error_quark(void); + + +#define SPICE_TYPE_WIN_USB_DRIVER (spice_win_usb_driver_get_type ()) +#define SPICE_WIN_USB_DRIVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriver)) +#define SPICE_IS_WIN_USB_DRIVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + SPICE_TYPE_WIN_USB_DRIVER)) +#define SPICE_WIN_USB_DRIVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverClass)) +#define SPICE_IS_WIN_USB_DRIVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ + SPICE_TYPE_WIN_USB_DRIVER)) +#define SPICE_WIN_USB_DRIVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ + SPICE_TYPE_WIN_USB_DRIVER, SpiceWinUsbDriverClass)) + +typedef struct _SpiceWinUsbDriver SpiceWinUsbDriver; +typedef struct _SpiceWinUsbDriverClass SpiceWinUsbDriverClass; +typedef struct _SpiceWinUsbDriverPrivate SpiceWinUsbDriverPrivate; + +struct _SpiceWinUsbDriver +{ + GObject parent; + + /*< private >*/ + SpiceWinUsbDriverPrivate *priv; + /* Do not add fields to this struct */ +}; + +struct _SpiceWinUsbDriverClass +{ + GObjectClass parent_class; +}; + +GType spice_win_usb_driver_get_type(void); + +SpiceWinUsbDriver *spice_win_usb_driver_new(GError **err); + + +void spice_win_usb_driver_install_async(SpiceWinUsbDriver *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean spice_win_usb_driver_install_finish(SpiceWinUsbDriver *self, + GAsyncResult *res, GError **err); + +void spice_win_usb_driver_uninstall_async(SpiceWinUsbDriver *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean spice_win_usb_driver_uninstall_finish(SpiceWinUsbDriver *self, + GAsyncResult *res, GError **err); + + + +SpiceUsbDevice *spice_win_usb_driver_get_device(SpiceWinUsbDriver *self); + +#define SPICE_WIN_USB_DRIVER_ERROR spice_win_usb_driver_error_quark() + +/** + * SpiceWinUsbDriverError: + * @SPICE_WIN_USB_DRIVER_ERROR_FAILED: generic error code + * @SPICE_WIN_USB_DRIVER_ERROR_MESSAGE: bad message read from clerk + * + * Error codes returned by spice-client API. + */ +typedef enum +{ + SPICE_WIN_USB_DRIVER_ERROR_FAILED, + SPICE_WIN_USB_DRIVER_ERROR_MESSAGE, +} SpiceWinUsbDriverError; + +GQuark spice_win_usb_driver_error_quark(void); + +G_END_DECLS + +#endif /* SPICE_WIN_USB_DRIVER_H */ diff --git a/src/wocky-http-proxy.c b/src/wocky-http-proxy.c new file mode 100644 index 0000000..f62f1fb --- /dev/null +++ b/src/wocky-http-proxy.c @@ -0,0 +1,520 @@ + /* wocky-http-proxy.c: Source for WockyHttpProxy + * + * Copyright (C) 2010 Collabora, Ltd. + * Copyright (C) 2014 Red Hat, Inc. + * @author Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> + * @author Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "wocky-http-proxy.h" + +#include <string.h> +#include <stdlib.h> + + +struct _WockyHttpProxy +{ + GObject parent; +}; + +struct _WockyHttpProxyClass +{ + GObjectClass parent_class; +}; + +static void wocky_http_proxy_iface_init (GProxyInterface *proxy_iface); + +#define wocky_http_proxy_get_type _wocky_http_proxy_get_type +G_DEFINE_TYPE_WITH_CODE (WockyHttpProxy, wocky_http_proxy, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_PROXY, + wocky_http_proxy_iface_init) + g_io_extension_point_set_required_type ( + g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME), + G_TYPE_PROXY); + g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME, + g_define_type_id, "http", 0)) + +static void +wocky_http_proxy_init (WockyHttpProxy *proxy) +{ +} + +#define HTTP_END_MARKER "\r\n\r\n" + +static gchar * +create_request (GProxyAddress *proxy_address, gboolean *has_cred) +{ + const gchar *hostname; + gint port; + const gchar *username; + const gchar *password; + GString *request; + gchar *ascii_hostname; + + if (has_cred) + *has_cred = FALSE; + + hostname = g_proxy_address_get_destination_hostname (proxy_address); + port = g_proxy_address_get_destination_port (proxy_address); + username = g_proxy_address_get_username (proxy_address); + password = g_proxy_address_get_password (proxy_address); + + request = g_string_new (NULL); + + ascii_hostname = g_hostname_to_ascii (hostname); + g_string_append_printf (request, + "CONNECT %s:%i HTTP/1.0\r\n" + "Host: %s:%i\r\n" + "Proxy-Connection: keep-alive\r\n" + "User-Agent: GLib/%i.%i\r\n", + ascii_hostname, port, + ascii_hostname, port, + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION); + g_free (ascii_hostname); + + if (username != NULL && password != NULL) + { + gchar *cred; + gchar *base64_cred; + + if (has_cred) + *has_cred = TRUE; + + cred = g_strdup_printf ("%s:%s", username, password); + base64_cred = g_base64_encode ((guchar *) cred, strlen (cred)); + g_free (cred); + g_string_append_printf (request, + "Proxy-Authorization: Basic %s\r\n", + base64_cred); + g_free (base64_cred); + } + + g_string_append (request, "\r\n"); + + return g_string_free (request, FALSE); +} + +static gboolean +check_reply (const gchar *buffer, gboolean has_cred, GError **error) +{ + gint err_code; + const gchar *ptr = buffer + 7; + + if (strncmp (buffer, "HTTP/1.", 7) != 0 + || (*ptr != '0' && *ptr != '1')) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + "Bad HTTP proxy reply"); + return FALSE; + } + + ptr++; + while (*ptr == ' ') ptr++; + + err_code = atoi (ptr); + + if (err_code < 200 || err_code >= 300) + { + const gchar *msg_start; + gchar *msg; + + while (g_ascii_isdigit (*ptr)) + ptr++; + + while (*ptr == ' ') + ptr++; + + msg_start = ptr; + + ptr = strchr (msg_start, '\r'); + + if (ptr == NULL) + ptr = strchr (msg_start, '\0'); + + msg = g_strndup (msg_start, ptr - msg_start); + + if (err_code == 407) + { + if (has_cred) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, + "HTTP proxy authentication failed"); + else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_NEED_AUTH, + "HTTP proxy authentication required"); + } + else if (msg[0] == '\0') + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + "Connection failed due to broken HTTP reply"); + else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + "HTTP proxy connection failed: %i %s", + err_code, msg); + + g_free (msg); + return FALSE; + } + + return TRUE; +} + +static GIOStream * +wocky_http_proxy_connect (GProxy *proxy, + GIOStream *io_stream, + GProxyAddress *proxy_address, + GCancellable *cancellable, + GError **error) +{ + GInputStream *in; + GOutputStream *out; + GDataInputStream *data_in = NULL; + gchar *buffer = NULL; + gboolean has_cred; + GIOStream *tlsconn = NULL; + + if (WOCKY_IS_HTTPS_PROXY (proxy)) + { + tlsconn = g_tls_client_connection_new (io_stream, + G_SOCKET_CONNECTABLE(proxy_address), + error); + if (!tlsconn) + goto error; + + GTlsCertificateFlags tls_validation_flags = G_TLS_CERTIFICATE_VALIDATE_ALL; +#ifdef DEBUG + tls_validation_flags &= ~(G_TLS_CERTIFICATE_UNKNOWN_CA | G_TLS_CERTIFICATE_BAD_IDENTITY); +#endif + g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn), + tls_validation_flags); + if (!g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn), cancellable, error)) + goto error; + + io_stream = tlsconn; + } + + in = g_io_stream_get_input_stream (io_stream); + out = g_io_stream_get_output_stream (io_stream); + + data_in = g_data_input_stream_new (in); + g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data_in), + FALSE); + + buffer = create_request (proxy_address, &has_cred); + if (!g_output_stream_write_all (out, buffer, strlen (buffer), NULL, + cancellable, error)) + goto error; + + g_free (buffer); + buffer = g_data_input_stream_read_until (data_in, HTTP_END_MARKER, NULL, + cancellable, error); + g_clear_object(&data_in); + + if (buffer == NULL) + { + if (error && (*error == NULL)) + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + "HTTP proxy server closed connection unexpectedly."); + goto error; + } + + if (!check_reply (buffer, has_cred, error)) + goto error; + + g_free (buffer); + + g_object_ref (io_stream); + g_clear_object (&tlsconn); + + return io_stream; + +error: + g_clear_object (&tlsconn); + g_clear_object (&data_in); + g_free (buffer); + return NULL; +} + + +typedef struct +{ + GTask *task; + GIOStream *io_stream; + gchar *buffer; + gssize length; + gssize offset; + GDataInputStream *data_in; + gboolean has_cred; +} ConnectAsyncData; + +static void request_write_cb (GObject *source, + GAsyncResult *res, + gpointer user_data); +static void reply_read_cb (GObject *source, + GAsyncResult *res, + gpointer user_data); + +static void +free_connect_data (ConnectAsyncData *data) +{ + if (data->io_stream != NULL) + g_object_unref (data->io_stream); + + g_free (data->buffer); + + if (data->data_in != NULL) + g_object_unref (data->data_in); + + g_free (data); +} + +static void +complete_async_from_error (ConnectAsyncData *data, GError *error) +{ + GTask *task = data->task; + + if (error == NULL) + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + "HTTP proxy server closed connection unexpectedly."); + + g_task_return_error(data->task, error); + g_object_unref (task); +} + +static void +do_write (GAsyncReadyCallback callback, ConnectAsyncData *data) +{ + GOutputStream *out; + out = g_io_stream_get_output_stream (data->io_stream); + g_output_stream_write_async (out, + data->buffer + data->offset, + data->length - data->offset, + G_PRIORITY_DEFAULT, g_task_get_cancellable(data->task), + callback, data); +} + +static void +stream_connected (ConnectAsyncData *data, + GIOStream *io_stream) +{ + GInputStream *in; + + data->io_stream = g_object_ref (io_stream); + in = g_io_stream_get_input_stream (io_stream); + data->data_in = g_data_input_stream_new (in); + g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data->data_in), + FALSE); + + do_write (request_write_cb, data); +} + +static void +handshake_completed (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GTlsConnection *conn = G_TLS_CONNECTION (source_object); + ConnectAsyncData *data = user_data; + GError *error = NULL; + + if (!g_tls_connection_handshake_finish (conn, res, &error)) + { + complete_async_from_error (data, error); + return; + } + + stream_connected (data, G_IO_STREAM (conn)); +} + +static void +wocky_http_proxy_connect_async (GProxy *proxy, + GIOStream *io_stream, + GProxyAddress *proxy_address, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + ConnectAsyncData *data; + + task = g_task_new (proxy, + cancellable, + callback, + user_data); + + data = g_new0 (ConnectAsyncData, 1); + data->task = task; + + data->buffer = create_request (proxy_address, &data->has_cred); + data->length = strlen (data->buffer); + data->offset = 0; + + if (WOCKY_IS_HTTPS_PROXY (proxy)) + { + GError *error = NULL; + GIOStream *tlsconn; + + tlsconn = g_tls_client_connection_new (io_stream, + G_SOCKET_CONNECTABLE(proxy_address), + &error); + if (!tlsconn) + { + complete_async_from_error (data, error); + return; + } + + g_return_if_fail (tlsconn != NULL); + + GTlsCertificateFlags tls_validation_flags = G_TLS_CERTIFICATE_VALIDATE_ALL; +#ifdef DEBUG + tls_validation_flags &= ~(G_TLS_CERTIFICATE_UNKNOWN_CA | G_TLS_CERTIFICATE_BAD_IDENTITY); +#endif + g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn), + tls_validation_flags); + g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn), + G_PRIORITY_DEFAULT, cancellable, + handshake_completed, data); + } + else + { + stream_connected (data, io_stream); + } +} + +static void +request_write_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + ConnectAsyncData *data = user_data; + gssize written; + + written = g_output_stream_write_finish (G_OUTPUT_STREAM (source), + res, &error); + if (written < 0) + { + complete_async_from_error (data, error); + return; + } + + data->offset += written; + + if (data->offset == data->length) + { + g_clear_pointer(&data->buffer, g_free); + + g_data_input_stream_read_until_async (data->data_in, + HTTP_END_MARKER, + G_PRIORITY_DEFAULT, + g_task_get_cancellable(data->task), + reply_read_cb, data); + + } + else + { + do_write (request_write_cb, data); + } +} + +static void +reply_read_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + ConnectAsyncData *data = user_data; + + data->buffer = g_data_input_stream_read_until_finish (data->data_in, + res, NULL, &error); + + if (data->buffer == NULL) + { + complete_async_from_error (data, error); + return; + } + + if (!check_reply (data->buffer, data->has_cred, &error)) + { + complete_async_from_error (data, error); + return; + } + + g_task_return_pointer (data->task, data, (GDestroyNotify) free_connect_data); + g_object_unref (data->task); +} + +static GIOStream * +wocky_http_proxy_connect_finish (GProxy *proxy, + GAsyncResult *result, + GError **error) +{ + GTask *task = G_TASK (result); + ConnectAsyncData *data = g_task_propagate_pointer (task, error); + + return data ? g_object_ref (data->io_stream) : NULL; +} + +static gboolean +wocky_http_proxy_supports_hostname (GProxy *proxy) +{ + return TRUE; +} + +static void +wocky_http_proxy_class_init (WockyHttpProxyClass *class) +{ +} + +static void +wocky_http_proxy_iface_init (GProxyInterface *proxy_iface) +{ + proxy_iface->connect = wocky_http_proxy_connect; + proxy_iface->connect_async = wocky_http_proxy_connect_async; + proxy_iface->connect_finish = wocky_http_proxy_connect_finish; + proxy_iface->supports_hostname = wocky_http_proxy_supports_hostname; +} + +struct _WockyHttpsProxy +{ + WockyHttpProxy parent; +}; + +struct _WockyHttpsProxyClass +{ + WockyHttpProxyClass parent_class; +}; + +#define wocky_https_proxy_get_type _wocky_https_proxy_get_type +G_DEFINE_TYPE_WITH_CODE (WockyHttpsProxy, wocky_https_proxy, WOCKY_TYPE_HTTP_PROXY, + G_IMPLEMENT_INTERFACE (G_TYPE_PROXY, + wocky_http_proxy_iface_init) + g_io_extension_point_set_required_type ( + g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME), + G_TYPE_PROXY); + g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME, + g_define_type_id, "https", 0)) + +static void +wocky_https_proxy_init (WockyHttpsProxy *proxy) +{ +} + +static void +wocky_https_proxy_class_init (WockyHttpsProxyClass *class) +{ +} diff --git a/src/wocky-http-proxy.h b/src/wocky-http-proxy.h new file mode 100644 index 0000000..38dad78 --- /dev/null +++ b/src/wocky-http-proxy.h @@ -0,0 +1,54 @@ + /* wocky-http-proxy.h: Header for WockyHttpProxy + * + * Copyright (C) 2010 Collabora, Ltd. + * @author Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _WOCKY_HTTP_PROXY_H_ +#define _WOCKY_HTTP_PROXY_H_ + +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define WOCKY_TYPE_HTTP_PROXY (_wocky_http_proxy_get_type ()) +#define WOCKY_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxy)) +#define WOCKY_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) +#define WOCKY_IS_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WOCKY_TYPE_HTTP_PROXY)) +#define WOCKY_IS_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WOCKY_TYPE_HTTP_PROXY)) +#define WOCKY_HTTP_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) + +typedef struct _WockyHttpProxy WockyHttpProxy; +typedef struct _WockyHttpProxyClass WockyHttpProxyClass; + +GType _wocky_http_proxy_get_type (void); + +#define WOCKY_TYPE_HTTPS_PROXY (_wocky_https_proxy_get_type ()) +#define WOCKY_HTTPS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxy)) +#define WOCKY_HTTPS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxyClass)) +#define WOCKY_IS_HTTPS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WOCKY_TYPE_HTTPS_PROXY)) +#define WOCKY_IS_HTTPS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WOCKY_TYPE_HTTPS_PROXY)) +#define WOCKY_HTTPS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WOCKY_TYPE_HTTPS_PROXY, WockyHttpsProxyClass)) + +typedef struct _WockyHttpsProxy WockyHttpsProxy; +typedef struct _WockyHttpsProxyClass WockyHttpsProxyClass; + +GType _wocky_https_proxy_get_type (void); + +G_END_DECLS + +#endif /* _WOCKY_HTTP_PROXY_H_ */ diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..1a8b768 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,45 @@ +NULL = + +noinst_PROGRAMS = +TESTS = coroutine \ + util \ + session \ + test-spice-uri \ + $(NULL) + +if WITH_PHODAV +TESTS += pipe +endif + +if WITH_POLKIT +TESTS += usb-acl-helper +noinst_PROGRAMS += mock-acl-helper +endif + +noinst_PROGRAMS += $(TESTS) + +AM_CPPFLAGS = \ + $(COMMON_CFLAGS) \ + $(GIO_CFLAGS) \ + $(SMARTCARD_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\"GSpice\" \ + $(NULL) + +AM_LDFLAGS = $(GIO_LIBS) -static + +LDADD = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(NULL) + +util_SOURCES = util.c +coroutine_SOURCES = coroutine.c +session_SOURCES = session.c +pipe_SOURCES = pipe.c +test_spice_uri_SOURCES = uri.c +usb_acl_helper_SOURCES = usb-acl-helper.c +usb_acl_helper_CFLAGS = -DTESTDIR=\"$(abs_builddir)\" +mock_acl_helper_SOURCES = mock-acl-helper.c + +-include $(top_srcdir)/git.mk diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..a15a113 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,1242 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_5) +TESTS = coroutine$(EXEEXT) util$(EXEEXT) session$(EXEEXT) \ + test-spice-uri$(EXEEXT) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) +@WITH_PHODAV_TRUE@am__append_1 = pipe +@WITH_POLKIT_TRUE@am__append_2 = usb-acl-helper +@WITH_POLKIT_TRUE@am__append_3 = mock-acl-helper +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@WITH_POLKIT_TRUE@am__EXEEXT_1 = mock-acl-helper$(EXEEXT) +am__EXEEXT_2 = +@WITH_PHODAV_TRUE@am__EXEEXT_3 = pipe$(EXEEXT) +@WITH_POLKIT_TRUE@am__EXEEXT_4 = usb-acl-helper$(EXEEXT) +am__EXEEXT_5 = coroutine$(EXEEXT) util$(EXEEXT) session$(EXEEXT) \ + test-spice-uri$(EXEEXT) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) +PROGRAMS = $(noinst_PROGRAMS) +am_coroutine_OBJECTS = coroutine.$(OBJEXT) +coroutine_OBJECTS = $(am_coroutine_OBJECTS) +coroutine_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +coroutine_DEPENDENCIES = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_mock_acl_helper_OBJECTS = mock-acl-helper.$(OBJEXT) +mock_acl_helper_OBJECTS = $(am_mock_acl_helper_OBJECTS) +mock_acl_helper_LDADD = $(LDADD) +mock_acl_helper_DEPENDENCIES = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +am_pipe_OBJECTS = pipe.$(OBJEXT) +pipe_OBJECTS = $(am_pipe_OBJECTS) +pipe_LDADD = $(LDADD) +pipe_DEPENDENCIES = $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +am_session_OBJECTS = session.$(OBJEXT) +session_OBJECTS = $(am_session_OBJECTS) +session_LDADD = $(LDADD) +session_DEPENDENCIES = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +am_test_spice_uri_OBJECTS = uri.$(OBJEXT) +test_spice_uri_OBJECTS = $(am_test_spice_uri_OBJECTS) +test_spice_uri_LDADD = $(LDADD) +test_spice_uri_DEPENDENCIES = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +am_usb_acl_helper_OBJECTS = usb_acl_helper-usb-acl-helper.$(OBJEXT) +usb_acl_helper_OBJECTS = $(am_usb_acl_helper_OBJECTS) +usb_acl_helper_LDADD = $(LDADD) +usb_acl_helper_DEPENDENCIES = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +usb_acl_helper_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(usb_acl_helper_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +am_util_OBJECTS = util.$(OBJEXT) +util_OBJECTS = $(am_util_OBJECTS) +util_LDADD = $(LDADD) +util_DEPENDENCIES = $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(coroutine_SOURCES) $(mock_acl_helper_SOURCES) \ + $(pipe_SOURCES) $(session_SOURCES) $(test_spice_uri_SOURCES) \ + $(usb_acl_helper_SOURCES) $(util_SOURCES) +DIST_SOURCES = $(coroutine_SOURCES) $(mock_acl_helper_SOURCES) \ + $(pipe_SOURCES) $(session_SOURCES) $(test_spice_uri_SOURCES) \ + $(usb_acl_helper_SOURCES) $(util_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +AM_CPPFLAGS = \ + $(COMMON_CFLAGS) \ + $(GIO_CFLAGS) \ + $(SMARTCARD_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\"GSpice\" \ + $(NULL) + +AM_LDFLAGS = $(GIO_LIBS) -static +LDADD = \ + $(top_builddir)/src/libspice-client-glib-2.0.la \ + $(NULL) + +util_SOURCES = util.c +coroutine_SOURCES = coroutine.c +session_SOURCES = session.c +pipe_SOURCES = pipe.c +test_spice_uri_SOURCES = uri.c +usb_acl_helper_SOURCES = usb-acl-helper.c +usb_acl_helper_CFLAGS = -DTESTDIR=\"$(abs_builddir)\" +mock_acl_helper_SOURCES = mock-acl-helper.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +coroutine$(EXEEXT): $(coroutine_OBJECTS) $(coroutine_DEPENDENCIES) $(EXTRA_coroutine_DEPENDENCIES) + @rm -f coroutine$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(coroutine_OBJECTS) $(coroutine_LDADD) $(LIBS) + +mock-acl-helper$(EXEEXT): $(mock_acl_helper_OBJECTS) $(mock_acl_helper_DEPENDENCIES) $(EXTRA_mock_acl_helper_DEPENDENCIES) + @rm -f mock-acl-helper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mock_acl_helper_OBJECTS) $(mock_acl_helper_LDADD) $(LIBS) + +pipe$(EXEEXT): $(pipe_OBJECTS) $(pipe_DEPENDENCIES) $(EXTRA_pipe_DEPENDENCIES) + @rm -f pipe$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipe_OBJECTS) $(pipe_LDADD) $(LIBS) + +session$(EXEEXT): $(session_OBJECTS) $(session_DEPENDENCIES) $(EXTRA_session_DEPENDENCIES) + @rm -f session$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(session_OBJECTS) $(session_LDADD) $(LIBS) + +test-spice-uri$(EXEEXT): $(test_spice_uri_OBJECTS) $(test_spice_uri_DEPENDENCIES) $(EXTRA_test_spice_uri_DEPENDENCIES) + @rm -f test-spice-uri$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_spice_uri_OBJECTS) $(test_spice_uri_LDADD) $(LIBS) + +usb-acl-helper$(EXEEXT): $(usb_acl_helper_OBJECTS) $(usb_acl_helper_DEPENDENCIES) $(EXTRA_usb_acl_helper_DEPENDENCIES) + @rm -f usb-acl-helper$(EXEEXT) + $(AM_V_CCLD)$(usb_acl_helper_LINK) $(usb_acl_helper_OBJECTS) $(usb_acl_helper_LDADD) $(LIBS) + +util$(EXEEXT): $(util_OBJECTS) $(util_DEPENDENCIES) $(EXTRA_util_DEPENDENCIES) + @rm -f util$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(util_OBJECTS) $(util_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coroutine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mock-acl-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb_acl_helper-usb-acl-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +usb_acl_helper-usb-acl-helper.o: usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(usb_acl_helper_CFLAGS) $(CFLAGS) -MT usb_acl_helper-usb-acl-helper.o -MD -MP -MF $(DEPDIR)/usb_acl_helper-usb-acl-helper.Tpo -c -o usb_acl_helper-usb-acl-helper.o `test -f 'usb-acl-helper.c' || echo '$(srcdir)/'`usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/usb_acl_helper-usb-acl-helper.Tpo $(DEPDIR)/usb_acl_helper-usb-acl-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='usb-acl-helper.c' object='usb_acl_helper-usb-acl-helper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(usb_acl_helper_CFLAGS) $(CFLAGS) -c -o usb_acl_helper-usb-acl-helper.o `test -f 'usb-acl-helper.c' || echo '$(srcdir)/'`usb-acl-helper.c + +usb_acl_helper-usb-acl-helper.obj: usb-acl-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(usb_acl_helper_CFLAGS) $(CFLAGS) -MT usb_acl_helper-usb-acl-helper.obj -MD -MP -MF $(DEPDIR)/usb_acl_helper-usb-acl-helper.Tpo -c -o usb_acl_helper-usb-acl-helper.obj `if test -f 'usb-acl-helper.c'; then $(CYGPATH_W) 'usb-acl-helper.c'; else $(CYGPATH_W) '$(srcdir)/usb-acl-helper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/usb_acl_helper-usb-acl-helper.Tpo $(DEPDIR)/usb_acl_helper-usb-acl-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='usb-acl-helper.c' object='usb_acl_helper-usb-acl-helper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(usb_acl_helper_CFLAGS) $(CFLAGS) -c -o usb_acl_helper-usb-acl-helper.obj `if test -f 'usb-acl-helper.c'; then $(CYGPATH_W) 'usb-acl-helper.c'; else $(CYGPATH_W) '$(srcdir)/usb-acl-helper.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +coroutine.log: coroutine$(EXEEXT) + @p='coroutine$(EXEEXT)'; \ + b='coroutine'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +util.log: util$(EXEEXT) + @p='util$(EXEEXT)'; \ + b='util'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +session.log: session$(EXEEXT) + @p='session$(EXEEXT)'; \ + b='session'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +test-spice-uri.log: test-spice-uri$(EXEEXT) + @p='test-spice-uri$(EXEEXT)'; \ + b='test-spice-uri'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipe.log: pipe$(EXEEXT) + @p='pipe$(EXEEXT)'; \ + b='pipe'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +usb-acl-helper.log: usb-acl-helper$(EXEEXT) + @p='usb-acl-helper$(EXEEXT)'; \ + b='usb-acl-helper'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/coroutine.c b/tests/coroutine.c new file mode 100644 index 0000000..bded593 --- /dev/null +++ b/tests/coroutine.c @@ -0,0 +1,132 @@ +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "coroutine.h" + +static gpointer co_entry_check_self(gpointer data) +{ + g_assert(data == coroutine_self()); + g_assert(!coroutine_self_is_main()); + + return NULL; +} + +static gpointer co_entry_42(gpointer data) +{ + g_assert(GPOINTER_TO_INT(data) == 42); + g_assert(!coroutine_self_is_main()); + + return GINT_TO_POINTER(0x42); +} + +static void test_coroutine_simple(void) +{ + struct coroutine *self = coroutine_self(); + struct coroutine co = { + .stack_size = 16 << 20, + .entry = co_entry_42, + }; + gpointer result; + + g_assert(coroutine_self_is_main()); + + coroutine_init(&co); + result = coroutine_yieldto(&co, GINT_TO_POINTER(42)); + g_assert_cmpint(GPOINTER_TO_INT(result), ==, 0x42); + + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*"); + coroutine_yieldto(&co, GINT_TO_POINTER(42)); + g_test_assert_expected_messages(); + + g_assert(self == coroutine_self()); + g_assert(coroutine_self_is_main()); +} + +static gpointer co_entry_two(gpointer data) +{ + struct coroutine *self = coroutine_self(); + struct coroutine co = { + .stack_size = 16 << 20, + .entry = co_entry_check_self, + }; + + g_assert(!coroutine_self_is_main()); + coroutine_init(&co); + coroutine_yieldto(&co, &co); + + g_assert(self == coroutine_self()); + return NULL; +} + +static void test_coroutine_two(void) +{ + struct coroutine *self = coroutine_self(); + struct coroutine co = { + .stack_size = 16 << 20, + .entry = co_entry_two, + }; + + coroutine_init(&co); + coroutine_yieldto(&co, NULL); + + g_assert(self == coroutine_self()); +} + +static gpointer co_entry_yield(gpointer data) +{ + gpointer val; + + g_assert(data == NULL); + val = coroutine_yield(GINT_TO_POINTER(1)); + g_assert_cmpint(GPOINTER_TO_INT(val), ==, 2); + + g_assert(!coroutine_self_is_main()); + + val = coroutine_yield(GINT_TO_POINTER(3)); + g_assert_cmpint(GPOINTER_TO_INT(val), ==, 4); + + return NULL; +} + +static void test_coroutine_yield(void) +{ + struct coroutine *self = coroutine_self(); + struct coroutine co = { + .stack_size = 16 << 20, + .entry = co_entry_yield, + }; + gpointer val; + + coroutine_init(&co); + val = coroutine_yieldto(&co, NULL); + + g_assert(self == coroutine_self()); + g_assert_cmpint(GPOINTER_TO_INT(val), ==, 1); + + val = coroutine_yieldto(&co, GINT_TO_POINTER(2)); + + g_assert(self == coroutine_self()); + g_assert_cmpint(GPOINTER_TO_INT(val), ==, 3); + + val = coroutine_yieldto(&co, GINT_TO_POINTER(4)); + + g_assert(self == coroutine_self()); + g_assert(val == NULL); + + g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*"); + coroutine_yieldto(&co, GINT_TO_POINTER(42)); + g_test_assert_expected_messages(); +} + +int main(int argc, char* argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/coroutine/simple", test_coroutine_simple); + g_test_add_func("/coroutine/two", test_coroutine_two); + g_test_add_func("/coroutine/yield", test_coroutine_yield); + + return g_test_run (); +} diff --git a/tests/mock-acl-helper.c b/tests/mock-acl-helper.c new file mode 100644 index 0000000..782ebaf --- /dev/null +++ b/tests/mock-acl-helper.c @@ -0,0 +1,90 @@ +/* + Copyright (C) 2016 Red Hat, 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <stdio.h> +#include <glib.h> +#include <gio/gunixinputstream.h> + +static int exit_status; +static int busnum, devnum; +static char path[PATH_MAX]; +static GMainLoop *loop; +static GDataInputStream *stdin_stream; + +static void cleanup(void) +{ + if (loop) + g_main_loop_quit(loop); +} + + +static void stdin_read_complete(GObject *src, GAsyncResult *res, gpointer data) +{ + char *s = NULL; + const char *response = NULL; + GError *err = NULL; + gsize len; + + s = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(src), res, + &len, &err); + + /* exit the program to return an early EOF to the caller */ + if (g_getenv("TEST_EOF")) + goto done; + + /* Don't return any response, but continue running to simulate a + * unresponsive binary */ + if (g_getenv("TEST_NORESPONSE")) + return; + + /* specify a particular resonse to be returned to the caller */ + response = g_getenv("TEST_RESPONSE"); + if (!response) + response = "SUCCESS"; + + fprintf(stdout, "%s\n", response); + fflush(stdout); + +done: + g_clear_error(&err); + g_free(s); + cleanup(); +} + +int main(void) +{ + GInputStream *stdin_unix_stream; + + loop = g_main_loop_new(NULL, FALSE); + + stdin_unix_stream = g_unix_input_stream_new(STDIN_FILENO, 0); + stdin_stream = g_data_input_stream_new(stdin_unix_stream); + g_data_input_stream_set_newline_type(stdin_stream, + G_DATA_STREAM_NEWLINE_TYPE_LF); + g_clear_object(&stdin_unix_stream); + g_data_input_stream_read_line_async(stdin_stream, G_PRIORITY_DEFAULT, NULL, + stdin_read_complete, NULL); + + g_main_loop_run(loop); + + g_object_unref(stdin_stream); + g_main_loop_unref(loop); + + return exit_status; +} diff --git a/tests/pipe.c b/tests/pipe.c new file mode 100644 index 0000000..01629da --- /dev/null +++ b/tests/pipe.c @@ -0,0 +1,525 @@ +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <locale.h> + +#include "giopipe.h" + +typedef struct _Fixture { + GIOStream *p1; + GIOStream *p2; + + GInputStream *ip1; + GOutputStream *op1; + GInputStream *ip2; + GOutputStream *op2; + + gchar buf[16]; + gchar *data; + guint16 data_len; + guint16 read_size; + guint16 total_read; + + GList *sources; + + GMainLoop *loop; + GCancellable *cancellable; + guint timeout; +} Fixture; + +static gboolean +stop_loop (gpointer data) +{ + GMainLoop *loop = data; + + g_main_loop_quit (loop); + g_assert_not_reached(); + + return G_SOURCE_REMOVE; +} + +static void +fixture_set_up(Fixture *fixture, + gconstpointer user_data) +{ + int i; + + spice_make_pipe(&fixture->p1, &fixture->p2); + g_assert_true(G_IS_IO_STREAM(fixture->p1)); + g_assert_true(G_IS_IO_STREAM(fixture->p2)); + + fixture->op1 = g_io_stream_get_output_stream(fixture->p1); + g_assert_true(G_IS_OUTPUT_STREAM(fixture->op1)); + fixture->ip1 = g_io_stream_get_input_stream(fixture->p1); + g_assert_true(G_IS_INPUT_STREAM(fixture->ip1)); + fixture->op2 = g_io_stream_get_output_stream(fixture->p2); + g_assert_true(G_IS_OUTPUT_STREAM(fixture->op2)); + fixture->ip2 = g_io_stream_get_input_stream(fixture->p2); + g_assert_true(G_IS_INPUT_STREAM(fixture->ip2)); + + for (i = 0; i < sizeof(fixture->buf); i++) { + fixture->buf[i] = 0x42 + i; + } + + fixture->sources = NULL; + fixture->cancellable = g_cancellable_new(); + fixture->loop = g_main_loop_new (NULL, FALSE); + fixture->timeout = g_timeout_add (1000, stop_loop, fixture->loop); +} + +static void +fixture_tear_down(Fixture *fixture, + gconstpointer user_data) +{ + g_clear_object(&fixture->p1); + g_clear_object(&fixture->p2); + + if (fixture->sources) + g_list_free_full(fixture->sources, (GDestroyNotify) g_source_unref); + + g_clear_pointer(&fixture->data, g_free); + g_clear_object(&fixture->cancellable); + g_source_remove(fixture->timeout); + g_main_loop_unref(fixture->loop); +} + +static void +test_pipe_readblock(Fixture *f, gconstpointer user_data) +{ + GError *error = NULL; + gssize size; + + size = g_input_stream_read(f->ip2, f->buf, 1, + f->cancellable, &error); + + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK); + + g_clear_error(&error); +} + +static void +test_pipe_writeblock(Fixture *f, gconstpointer user_data) +{ + GError *error = NULL; + gssize size; + + size = g_output_stream_write(f->op1, "", 1, + f->cancellable, &error); + + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK); + + g_clear_error(&error); +} + +static void +write_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + GMainLoop *loop = user_data; + gssize nbytes; + + nbytes = g_output_stream_write_finish(G_OUTPUT_STREAM(source), result, &error); + + g_assert_no_error(error); + g_assert_cmpint(nbytes, >, 0); + g_clear_error(&error); + + g_main_loop_quit (loop); +} + +static void +read_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + gssize nbytes, expected = GPOINTER_TO_INT(user_data); + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + + g_assert_cmpint(nbytes, ==, expected); + g_assert_no_error(error); + g_clear_error(&error); +} + +static void +test_pipe_writeread(Fixture *f, gconstpointer user_data) +{ + g_output_stream_write_async(f->op1, "", 1, G_PRIORITY_DEFAULT, + f->cancellable, write_cb, f->loop); + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, read_cb, GINT_TO_POINTER(1)); + + g_main_loop_run (f->loop); + + g_output_stream_write_async(f->op1, "", 1, G_PRIORITY_DEFAULT, + f->cancellable, write_cb, f->loop); + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, read_cb, GINT_TO_POINTER(1)); + + g_main_loop_run (f->loop); +} + +static void +test_pipe_readwrite(Fixture *f, gconstpointer user_data) +{ + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, read_cb, GINT_TO_POINTER(1)); + g_output_stream_write_async(f->op1, "", 1, G_PRIORITY_DEFAULT, + f->cancellable, write_cb, f->loop); + + g_main_loop_run (f->loop); +} + +static void +test_pipe_write16read8(Fixture *f, gconstpointer user_data) +{ + g_output_stream_write_async(f->op1, "0123456789abcdef", 16, G_PRIORITY_DEFAULT, + f->cancellable, write_cb, f->loop); + g_input_stream_read_async(f->ip2, f->buf, 8, G_PRIORITY_DEFAULT, + f->cancellable, read_cb, GINT_TO_POINTER(8)); + + g_main_loop_run (f->loop); + + /* check next read would block */ + test_pipe_readblock(f, user_data); +} + +static void +test_pipe_write8read16(Fixture *f, gconstpointer user_data) +{ + g_output_stream_write_async(f->op1, "01234567", 8, G_PRIORITY_DEFAULT, + f->cancellable, write_cb, f->loop); + g_input_stream_read_async(f->ip2, f->buf, 16, G_PRIORITY_DEFAULT, + f->cancellable, read_cb, GINT_TO_POINTER(8)); + + g_main_loop_run (f->loop); + + /* check next read would block */ + test_pipe_writeblock(f, user_data); +} + +static void +readclose_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + gssize nbytes; + GMainLoop *loop = user_data; + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CLOSED); + g_clear_error(&error); + + g_main_loop_quit (loop); +} + +static void +test_pipe_readclosestream(Fixture *f, gconstpointer user_data) +{ + GError *error = NULL; + + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, readclose_cb, f->loop); + g_io_stream_close(f->p1, f->cancellable, &error); + + g_main_loop_run (f->loop); +} + +static void +test_pipe_readclose(Fixture *f, gconstpointer user_data) +{ + GError *error = NULL; + + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, readclose_cb, f->loop); + g_output_stream_close(f->op1, f->cancellable, &error); + + g_main_loop_run (f->loop); +} + +static void +readcancel_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + gssize nbytes; + GMainLoop *loop = user_data; + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_CLOSED); + g_clear_error(&error); + + g_main_loop_quit (loop); +} + +static void +test_pipe_readcancel(Fixture *f, gconstpointer user_data) +{ + GError *error = NULL; + + g_input_stream_read_async(f->ip2, f->buf, 1, G_PRIORITY_DEFAULT, + f->cancellable, readcancel_cb, f->loop); + g_output_stream_close(f->op1, f->cancellable, &error); + + g_main_loop_run (f->loop); +} + +static gchar * +get_test_data(gint n) +{ + GString *s = g_string_sized_new(n); + const gchar *data = "01234567abcdefgh"; + gint i, q; + + q = n / 16; + for (i = 0; i < q; i++) + s = g_string_append(s, data); + + s = g_string_append_len(s, data, (n % 16)); + return g_string_free(s, FALSE); +} + +static void +write_all_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gsize nbytes; + + g_output_stream_write_all_finish(G_OUTPUT_STREAM(source), result, &nbytes, &error); + g_assert_no_error(error); + g_assert_cmpint(nbytes, ==, f->data_len); + g_clear_error(&error); + + g_main_loop_quit (f->loop); +} + +static void +read_chunk_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gssize nbytes; + gboolean data_match; + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + g_assert_no_error(error); + g_assert_cmpint(nbytes, >, 0); + data_match = (g_ascii_strncasecmp(f->data + f->total_read, f->buf, nbytes) == 0); + g_assert_true(data_match); + + f->total_read += nbytes; + if (f->total_read != f->data_len) { + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb, f); + } +} + +static void +test_pipe_write_all_64_read_chunks_16(Fixture *f, gconstpointer user_data) +{ + f->data_len = 64; + f->data = get_test_data(f->data_len); + f->read_size = 16; + f->total_read = 0; + + g_output_stream_write_all_async(f->op1, f->data, f->data_len, G_PRIORITY_DEFAULT, + f->cancellable, write_all_cb, f); + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb, f); + g_main_loop_run (f->loop); +} + +static void +read_chunk_cb_and_try_write(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gssize nbytes; + gboolean data_match; + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + g_assert_no_error(error); + g_assert_cmpint(nbytes, >, 0); + data_match = (g_ascii_strncasecmp(f->data + f->total_read, f->buf, nbytes) == 0); + g_assert_true(data_match); + + f->total_read += nbytes; + if (f->total_read != f->data_len) { + /* try write before reading another chunk */ + g_output_stream_write(f->op1, "", 1, f->cancellable, &error); + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_PENDING); + g_clear_error(&error); + + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb_and_try_write, f); + } +} + +static void +test_pipe_concurrent_write(Fixture *f, gconstpointer user_data) +{ + f->data_len = 64; + f->data = get_test_data(f->data_len); + f->read_size = 16; + f->total_read = 0; + + g_output_stream_write_all_async(f->op1, f->data, f->data_len, G_PRIORITY_DEFAULT, + f->cancellable, write_all_cb, f); + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb_and_try_write, f); + g_main_loop_run (f->loop); +} + +static void +write_all_cb_zombie_check(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gsize nbytes; + GList *it; + + g_output_stream_write_all_finish(G_OUTPUT_STREAM(source), result, &nbytes, &error); + g_assert_no_error(error); + g_assert_cmpint(nbytes, ==, f->data_len); + g_clear_error(&error); + + for (it = f->sources; it != NULL; it = it->next) { + GSource *s = it->data; + g_assert_true (g_source_is_destroyed (s)); + } + + g_main_loop_quit (f->loop); +} + +static gboolean +source_cb (gpointer user_data) +{ + return G_SOURCE_REMOVE; +} + +#define NUM_OF_DUMMY_GSOURCE 1000 + +static void +read_chunk_cb_and_do_zombie(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gssize nbytes; + gboolean data_match, try_zombie; + gint i; + + nbytes = g_input_stream_read_finish(G_INPUT_STREAM(source), result, &error); + g_assert_no_error(error); + g_assert_cmpint(nbytes, >, 0); + data_match = (g_ascii_strncasecmp(f->data + f->total_read, f->buf, nbytes) == 0); + g_assert_true(data_match); + + /* Simulate more Pollable GSources created to read from Pipe; This should + * not fail but giopipe does not allow concurrent read/write which means + * that only the *last* GSource created will be the one that does the actual + * read; The other GSources that are still active should be dispatched. + * (In this test, only the real GSource created in g_input_stream_read_async + * will read the data) */ + + /* Create GSources in all iterations besides the last one, simply because + * it is convenient! The execution of the last interaction should give enough + * time for for all dummy GSources being detached. */ + f->total_read += nbytes; + try_zombie = (f->total_read + f->read_size < f->data_len); + + if (try_zombie) { + for (i = 0; i < NUM_OF_DUMMY_GSOURCE/2; i++) { + GSource *s = g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(f->ip2), NULL); + g_source_set_callback(s, source_cb, NULL, NULL); + g_source_attach(s, NULL); + f->sources = g_list_prepend(f->sources, s); + } + } + + if (f->total_read != f->data_len) + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb_and_do_zombie, f); + + if (try_zombie) { + for (i = 0; i < NUM_OF_DUMMY_GSOURCE/2; i++) { + GSource *s = g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(f->ip2), NULL); + g_source_set_callback(s, source_cb, NULL, NULL); + g_source_attach(s, NULL); + f->sources = g_list_prepend(f->sources, s); + } + } +} + +static void +test_pipe_zombie_sources(Fixture *f, gconstpointer user_data) +{ + gint i; + f->data_len = 64; + f->data = get_test_data(f->data_len); + f->read_size = 16; + f->total_read = 0; + + g_output_stream_write_all_async(f->op1, f->data, f->data_len, G_PRIORITY_DEFAULT, + f->cancellable, write_all_cb_zombie_check, f); + g_input_stream_read_async(f->ip2, f->buf, f->read_size, G_PRIORITY_DEFAULT, + f->cancellable, read_chunk_cb_and_do_zombie, f); + g_main_loop_run (f->loop); +} + +int main(int argc, char* argv[]) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + g_test_add("/pipe/readblock", Fixture, NULL, + fixture_set_up, test_pipe_readblock, + fixture_tear_down); + + g_test_add("/pipe/writeblock", Fixture, NULL, + fixture_set_up, test_pipe_writeblock, + fixture_tear_down); + + g_test_add("/pipe/writeread", Fixture, NULL, + fixture_set_up, test_pipe_writeread, + fixture_tear_down); + + g_test_add("/pipe/readwrite", Fixture, NULL, + fixture_set_up, test_pipe_readwrite, + fixture_tear_down); + + g_test_add("/pipe/write16read8", Fixture, NULL, + fixture_set_up, test_pipe_write16read8, + fixture_tear_down); + + g_test_add("/pipe/write8read16", Fixture, NULL, + fixture_set_up, test_pipe_write8read16, + fixture_tear_down); + + g_test_add("/pipe/write-all64-read-chunks16", Fixture, NULL, + fixture_set_up, test_pipe_write_all_64_read_chunks_16, + fixture_tear_down); + + g_test_add("/pipe/concurrent-write", Fixture, NULL, + fixture_set_up, test_pipe_concurrent_write, + fixture_tear_down); + + g_test_add("/pipe/zombie-sources", Fixture, NULL, + fixture_set_up, test_pipe_zombie_sources, + fixture_tear_down); + + g_test_add("/pipe/readclosestream", Fixture, NULL, + fixture_set_up, test_pipe_readclosestream, + fixture_tear_down); + + g_test_add("/pipe/readclose", Fixture, NULL, + fixture_set_up, test_pipe_readclose, + fixture_tear_down); + + g_test_add("/pipe/readcancel", Fixture, NULL, + fixture_set_up, test_pipe_readcancel, + fixture_tear_down); + + return g_test_run(); +} diff --git a/tests/session.c b/tests/session.c new file mode 100644 index 0000000..d065b60 --- /dev/null +++ b/tests/session.c @@ -0,0 +1,72 @@ +#include <spice-client.h> + +static void test_session_uri(void) +{ + SpiceSession *s; + gint i; + + struct { + gchar *port; + gchar *tls_port; + gchar *uri_input; + gchar *uri_output; + } tests[] = { + /* Arguments with empty value */ + { "5900", NULL, + "spice://localhost?port=5900&tls-port=", + "spice://localhost?port=5900&" }, + { "5910", NULL, + "spice://localhost?tls-port=&port=5910", + "spice://localhost?port=5910&" }, + { NULL, "5920", + "spice://localhost?tls-port=5920&port=", + "spice://localhost?tls-port=5920" }, + { NULL, "5930", + "spice://localhost?port=&tls-port=5930", + "spice://localhost?tls-port=5930" }, + }; + + /* Set URI and check URI, port and tls_port */ + for (i = 0; i < G_N_ELEMENTS(tests); i++) { + gchar *uri, *port, *tls_port; + + s = spice_session_new(); + g_object_set(s, "uri", tests[i].uri_input, NULL); + g_object_get(s, + "uri", &uri, + "port", &port, + "tls-port", &tls_port, + NULL); + g_assert_cmpstr(tests[i].uri_output, ==, uri); + g_assert_cmpstr(tests[i].port, ==, port); + g_assert_cmpstr(tests[i].tls_port, ==, tls_port); + g_clear_pointer(&uri, g_free); + g_clear_pointer(&port, g_free); + g_clear_pointer(&tls_port, g_free); + g_object_unref(s); + } + + /* Set port and tls_port, check URI */ + for (i = 0; i < G_N_ELEMENTS(tests); i++) { + gchar *uri; + + s = spice_session_new(); + g_object_set(s, + "port", tests[i].port, + "tls-port", tests[i].tls_port, + NULL); + g_object_get(s, "uri", &uri, NULL); + g_assert_cmpstr(tests[i].uri_output, ==, uri); + g_clear_pointer(&uri, g_free); + g_object_unref(s); + } +} + +int main(int argc, char* argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/session/uri", test_session_uri); + + return g_test_run(); +} diff --git a/tests/uri.c b/tests/uri.c new file mode 100644 index 0000000..5bfed2d --- /dev/null +++ b/tests/uri.c @@ -0,0 +1,148 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#include <glib.h> +#include <spice-client.h> +#include "spice-uri-priv.h" + +/* GLIB_CHECK_VERSION(2, 40, 0) */ +#ifndef g_assert_nonnull +#define g_assert_nonnull g_assert +#endif + +struct test_case { + gchar *uri; + gchar *scheme; + gchar *hostname; + guint port; + gchar *user; + gchar *password; + gchar *error_msg; +}; + +static void test_spice_uri_bad(const struct test_case invalid_test_cases[], const guint cases_cnt) +{ + guint i; + + SpiceURI *uri = spice_uri_new(); + g_assert_nonnull(uri); + + for (i = 0; i < cases_cnt; i++) { + GError *error = NULL; + g_assert_false(spice_uri_parse(uri, invalid_test_cases[i].uri, &error)); + g_assert_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED); + g_assert_cmpstr(error->message, ==, invalid_test_cases[i].error_msg); + g_error_free(error); + } + + g_object_unref(uri); +} + +static void test_spice_uri_good(const struct test_case valid_test_cases[], const guint cases_cnt) +{ + guint i; + + SpiceURI *uri = spice_uri_new(); + g_assert_nonnull(uri); + + for (i = 0; i < cases_cnt; i++) { + GError *error = NULL; + g_assert_true(spice_uri_parse(uri, valid_test_cases[i].uri, &error)); + g_assert_cmpstr(spice_uri_get_scheme(uri), ==, valid_test_cases[i].scheme); + g_assert_cmpstr(spice_uri_get_hostname(uri), ==, valid_test_cases[i].hostname); + g_assert_cmpstr(spice_uri_get_user(uri), ==, valid_test_cases[i].user); + g_assert_cmpstr(spice_uri_get_password(uri), ==, valid_test_cases[i].password); + g_assert_cmpuint(spice_uri_get_port(uri), ==, valid_test_cases[i].port); + g_assert_no_error(error); + } + + g_object_unref(uri); +} + +static void test_spice_uri_ipv4_bad(void) +{ + const struct test_case invalid_test_cases[] = { + {"http://:80", "http", NULL, 80, NULL, NULL, "Invalid hostname in uri address"}, + {"http://", "http", NULL, 3128, NULL, NULL, "Invalid hostname in uri address"}, + {"http://127.0.0.1:port", "http", "127.0.0.1", 3128, NULL, NULL, + "Invalid uri port: port"}, + {"http://127.0.0.1:", "http", "127.0.0.1", 3128, NULL, NULL, "Missing uri port"}, + {"http://127.0.0.1:-80", "http", "127.0.0.1", 3128, NULL, NULL, "Port out of range"}, + {"http://127.0.0.1:4294967396", "http", "127.0.0.1", 3128, NULL, NULL, "Port out of range"}, + {"http://127.0.0.1:12345678901234", "http", "127.0.0.1", 3128, NULL, NULL, "Port out of range"}, + {"scheme://192.168.1.1:3128", "http", "127.0.0.1", 3128, NULL, NULL, + "Invalid uri scheme for proxy: scheme"}, + }; + + test_spice_uri_bad(invalid_test_cases, G_N_ELEMENTS(invalid_test_cases)); +} + +static void test_spice_uri_ipv4_good(void) +{ + const struct test_case valid_test_cases[] = { + {"http://127.0.0.1/", "http", "127.0.0.1", 3128, NULL, NULL, NULL}, + {"https://127.0.0.1", "https", "127.0.0.1", 3129, NULL, NULL, NULL}, + {"127.0.0.1", "http", "127.0.0.1", 3128, NULL, NULL, NULL}, + {"http://user:password@host:80", "http", "host", 80, "user", "password", NULL}, + {"https://host:42", "https", "host", 42, NULL, NULL, NULL}, /* tests resetting of username & password */ + }; + + test_spice_uri_good(valid_test_cases, G_N_ELEMENTS(valid_test_cases)); +} + +static void test_spice_uri_ipv6_bad(void) +{ + const struct test_case invalid_test_cases[] = { + {"http://[]:80", "http", NULL, 80, NULL, NULL, "Invalid hostname in uri address"}, + {"http://[::1", "http", NULL, 3128, NULL, NULL, "Missing ']' in ipv6 uri"}, + {"http://[host]1234", "http", "host", 3128, NULL, NULL, "Invalid uri address"}, + {"http://[host]foo/", "http", "host", 3128, NULL, NULL, "Invalid uri address"}, + {"http://[::1]:port", "http", "::1", 3128, NULL, NULL, "Invalid uri port: port"}, + {"http://[::127.0.0.1]:", "http", "::127.0.0.1", 3128, NULL, NULL, "Missing uri port"}, + {"http://[::127.0.0.1]:-42", "http", "::127.0.0.1", 3128, NULL, NULL, "Port out of range"}, + {"[3ffe:2a00:100:7031::1]:42000000", "http", "3ffe:2a00:100:7031::1", 3128, NULL, NULL, "Port out of range"}, + {"scheme://[3ffe::192.168.1.1]:3128", "http", "3ffe::192.168.1.1", 3128, NULL, NULL, + "Invalid uri scheme for proxy: scheme"}, + }; + + test_spice_uri_bad(invalid_test_cases, G_N_ELEMENTS(invalid_test_cases)); +} + +static void test_spice_uri_ipv6_good(void) +{ + const struct test_case valid_test_cases[] = { + {"http://user:password@[host]:80/", "http", "host", 80, "user", "password", NULL}, + {"http://user@[1080:0:0:0:8:800:200C:4171]:100", "http", "1080:0:0:0:8:800:200C:4171", 100, + "user", NULL, NULL}, + {"https://[1080::8:800:200C:417A]", "https", "1080::8:800:200C:417A", 3129, NULL, NULL, NULL}, + {"[3ffe:2a00:100:7031::1]", "http", "3ffe:2a00:100:7031::1", 3128, NULL, NULL, NULL}, + }; + + test_spice_uri_good(valid_test_cases, G_N_ELEMENTS(valid_test_cases)); +} + +int main(int argc, char* argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/spice_uri/ipv4/bad-uri", test_spice_uri_ipv4_bad); + g_test_add_func("/spice_uri/ipv4/good-uri", test_spice_uri_ipv4_good); + g_test_add_func("/spice_uri/ipv6/bad-uri", test_spice_uri_ipv6_bad); + g_test_add_func("/spice_uri/ipv6/good-uri", test_spice_uri_ipv6_good); + + return g_test_run(); +} diff --git a/tests/usb-acl-helper.c b/tests/usb-acl-helper.c new file mode 100644 index 0000000..41dda5d --- /dev/null +++ b/tests/usb-acl-helper.c @@ -0,0 +1,226 @@ +/* + Copyright (C) 2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> +#include "usb-acl-helper.h" + +typedef struct { + SpiceUsbAclHelper *acl_helper; + GCancellable *cancellable; + GMainLoop *loop; + guint timeout_source; +} Fixture; + +gboolean abort_test(gpointer user_data) +{ + Fixture *fixture = user_data; + g_cancellable_cancel(fixture->cancellable); + fixture->timeout_source = 0; + return G_SOURCE_REMOVE; +} + +gboolean cancel_test(gpointer user_data) +{ + Fixture *fixture = user_data; + g_cancellable_cancel(fixture->cancellable); + return G_SOURCE_REMOVE; +} + +static void data_setup(Fixture *fixture, gconstpointer user_data) +{ + g_setenv("SPICE_USB_ACL_BINARY", TESTDIR"/mock-acl-helper", TRUE); + fixture->cancellable = g_cancellable_new(); + fixture->acl_helper = spice_usb_acl_helper_new(); + fixture->loop = g_main_loop_new(NULL, FALSE); + /* abort test after 2 seconds if it hasn't yet completed */ + fixture->timeout_source = g_timeout_add_seconds(2, abort_test, fixture); +} + +static void data_teardown(Fixture *fixture, gconstpointer user_data) +{ + if (fixture->timeout_source) + g_source_remove(fixture->timeout_source); + g_object_unref(fixture->cancellable); + g_object_unref(fixture->acl_helper); + g_main_loop_unref(fixture->loop); + g_unsetenv("SPICE_USB_ACL_BINARY"); +} + + +static void success_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + if (!spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error)) + g_error("%s", error->message); + g_main_loop_quit(f->loop); +} + +static void test_acl_helper_success(Fixture *fixture, gconstpointer user_data) +{ + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, success_cb, fixture); + g_main_loop_run(fixture->loop); +} + +static void spawn_fail_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gboolean success = spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error); + g_assert(!success); + g_assert (error->domain == G_SPAWN_ERROR); + g_clear_error(&error); + g_main_loop_quit(f->loop); +} + +static void test_acl_helper_spawn_fail(Fixture *fixture, gconstpointer user_data) +{ + g_setenv("SPICE_USB_ACL_BINARY", "does-not-exist", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, spawn_fail_cb, + fixture); + g_main_loop_run(fixture->loop); +} + +static void early_eof_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gboolean success = spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error); + g_assert(!success); + g_assert(error->domain == SPICE_CLIENT_ERROR); + g_assert(error->code == SPICE_CLIENT_ERROR_FAILED); + g_clear_error(&error); + g_main_loop_quit(f->loop); +} + +/* helper sends EOF before sending a response */ +static void test_acl_helper_early_eof(Fixture *fixture, gconstpointer user_data) +{ + g_setenv("TEST_EOF", "1", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, early_eof_cb, fixture); + g_main_loop_run(fixture->loop); + g_unsetenv("TEST_EOF"); +} + +static void helper_canceled_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gboolean success = spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error); + g_assert(!success); + g_assert(error->domain == G_IO_ERROR); + g_assert(error->code == G_IO_ERROR_CANCELLED); + g_clear_error(&error); + g_main_loop_quit(f->loop); +} + +static void test_acl_helper_helper_canceled(Fixture *fixture, gconstpointer user_data) +{ + g_setenv("TEST_RESPONSE", "CANCELED", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, helper_canceled_cb, fixture); + g_main_loop_run(fixture->loop); + g_unsetenv("TEST_RESPONSE"); +} + +static void helper_error_response_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gboolean success = spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error); + g_assert(!success); + g_assert(error->domain == SPICE_CLIENT_ERROR); + g_assert(error->code == SPICE_CLIENT_ERROR_FAILED); + g_clear_error(&error); + g_main_loop_quit(f->loop); +} + +static void test_acl_helper_error_response(Fixture *fixture, gconstpointer user_data) +{ + g_setenv("TEST_RESPONSE", "Not authorized", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, helper_error_response_cb, fixture); + g_main_loop_run(fixture->loop); + g_unsetenv("TEST_RESPONSE"); +} + +static void client_canceled_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Fixture *f = user_data; + GError *error = NULL; + gboolean success = spice_usb_acl_helper_open_acl_finish(SPICE_USB_ACL_HELPER(source), result, &error); + g_assert(!success); + g_assert(error->domain == G_IO_ERROR); + g_assert(error->code == G_IO_ERROR_CANCELLED); + g_clear_error(&error); + g_main_loop_quit(f->loop); +} + +static void test_acl_helper_client_canceled(Fixture *fixture, gconstpointer user_data) +{ + /* ensure that the acl-helper does not have respond, so we can cancel the + * task before we get a response from the helper binary */ + g_setenv("TEST_NORESPONSE", "1", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, client_canceled_cb, fixture); + g_idle_add(cancel_test, fixture); + g_main_loop_run(fixture->loop); + g_unsetenv("TEST_NORESPONSE"); +} + +static void test_acl_helper_no_response(Fixture *fixture, gconstpointer user_data) +{ + /* ensure that the acl-helper does not have respond, so we can cancel the + * task before we get a response from the helper binary */ + g_setenv("TEST_NORESPONSE", "1", TRUE); + spice_usb_acl_helper_open_acl_async(fixture->acl_helper, 1, 1, + fixture->cancellable, client_canceled_cb, fixture); + g_main_loop_run(fixture->loop); + g_unsetenv("TEST_NORESPONSE"); +} + +int main(int argc, char* argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add("/usb-acl-helper/success", Fixture, NULL, + data_setup, test_acl_helper_success, data_teardown); + g_test_add("/usb-acl-helper/spawn-fail", Fixture, NULL, + data_setup, test_acl_helper_spawn_fail, data_teardown); + g_test_add("/usb-acl-helper/early-eof", Fixture, NULL, + data_setup, test_acl_helper_early_eof, data_teardown); + g_test_add("/usb-acl-helper/helper-canceled", Fixture, NULL, + data_setup, test_acl_helper_helper_canceled, data_teardown); + g_test_add("/usb-acl-helper/helper-error", Fixture, NULL, + data_setup, test_acl_helper_error_response, data_teardown); + g_test_add("/usb-acl-helper/client-canceled", Fixture, NULL, + data_setup, test_acl_helper_client_canceled, data_teardown); + g_test_add("/usb-acl-helper/no-response", Fixture, NULL, + data_setup, test_acl_helper_no_response, data_teardown); + /* additional possible test cases: + * - unable to set nonblocking flag on io channel? + * - unable to write bus number to helper binary + * - unable to flush channel + * - read_line from helper binary returns something other than G_IO_STATUS_NORMAL + */ + + return g_test_run (); +} + diff --git a/tests/util.c b/tests/util.c new file mode 100644 index 0000000..dcc9770 --- /dev/null +++ b/tests/util.c @@ -0,0 +1,208 @@ +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#define __SPICE_CLIENT_H_INSIDE__ +#include "spice-util-priv.h" + +enum { + DOS2UNIX = 1 << 0, + UNIX2DOS = 1 << 1, +}; + +static const struct { + const gchar *d; + const gchar *u; + glong flags; +} dosunix[] = { + { "", "", DOS2UNIX|UNIX2DOS }, + { "a", "a", DOS2UNIX|UNIX2DOS }, + { "\r\n", "\n", DOS2UNIX|UNIX2DOS }, + { "\r\n\r\n", "\n\n", DOS2UNIX|UNIX2DOS }, + { "a\r\n", "a\n", DOS2UNIX|UNIX2DOS }, + { "a\r\n\r\n", "a\n\n", DOS2UNIX|UNIX2DOS }, + { "\r\n\r\na\r\n\r\n", "\n\na\n\n", DOS2UNIX|UNIX2DOS }, + { "1\r\n\r\na\r\n\r\n2", "1\n\na\n\n2", DOS2UNIX|UNIX2DOS }, + { "\n", "\n", DOS2UNIX }, + { "\n\n", "\n\n", DOS2UNIX }, + { "\r\n", "\r\n", UNIX2DOS }, + { "\r\r\n", "\r\r\n", UNIX2DOS }, + { "é\r\né", "é\né", DOS2UNIX|UNIX2DOS }, + { "\r\né\r\né\r\n", "\né\né\n", DOS2UNIX|UNIX2DOS } + /* TODO: add some utf8 test cases */ +}; + +static void test_dos2unix(void) +{ + GError *err = NULL; + gchar *tmp; + unsigned int i; + + for (i = 0; i < G_N_ELEMENTS(dosunix); i++) { + if (!(dosunix[i].flags & DOS2UNIX)) + continue; + + tmp = spice_dos2unix(dosunix[i].d, -1, &err); + g_assert_cmpstr(tmp, ==, dosunix[i].u); + g_assert_no_error(err); + g_free(tmp); + + /* including ending \0 */ + tmp = spice_dos2unix(dosunix[i].d, strlen(dosunix[i].d) + 1, &err); + g_assert_cmpstr(tmp, ==, dosunix[i].u); + g_assert_no_error(err); + g_free(tmp); + } +} + +static void test_unix2dos(void) +{ + GError *err = NULL; + gchar *tmp; + unsigned int i; + + for (i = 0; i < G_N_ELEMENTS(dosunix); i++) { + if (!(dosunix[i].flags & UNIX2DOS)) + continue; + + tmp = spice_unix2dos(dosunix[i].u, -1, &err); + g_assert_cmpstr(tmp, ==, dosunix[i].d); + g_assert_no_error(err); + g_free(tmp); + + /* including ending \0 */ + tmp = spice_unix2dos(dosunix[i].u, strlen(dosunix[i].u) + 1, &err); + g_assert_cmpstr(tmp, ==, dosunix[i].d); + g_assert_no_error(err); + g_free(tmp); + } +} + +static const struct { + unsigned width; + unsigned height; + gchar *and; + gchar *xor; + gchar *dest; +} mono[] = { + { + 8, 6, + "11111111" + "11111111" + "11111111" + "11111111" + "11111111" + "11111111" + , + "00000000" + "00000000" + "00000100" + "00000100" + "00000000" + "00000000" + , + "0000" "0000" "0000" "0000" "0000" "0000" "0000" "0000" + "0000" "0000" "0000" "0000" "0001" "0001" "0001" "0000" + "0000" "0000" "0000" "0000" "0001" "1111" "0001" "0000" + "0000" "0000" "0000" "0000" "0001" "1111" "0001" "0000" + "0000" "0000" "0000" "0000" "0001" "0001" "0001" "0000" + "0000" "0000" "0000" "0000" "0000" "0000" "0000" "0000" + } +}; + +static void set_bit(guint8 *d, unsigned bit, unsigned value) +{ + if (value) { + *d |= (0x80 >> bit); + } else { + *d &= ~(0x80 >> bit); + } +} + +static void test_set_bit(void) +{ + struct { + unsigned len; + gchar *src; + gchar *dest; + } tests[] = { + { + 4, + "1111", + "\xf0", + }, + { + 16, + "1111011100110001", + "\xf7\x31", + } + }; + unsigned int i, j, bit; + guint8 *dest; + unsigned int bytes; + + for (i = 0 ; i < G_N_ELEMENTS(tests); ++i) { + bytes = (tests[i].len + 7) / 8; + dest = g_malloc0(bytes); + for (j = 0 ; j < tests[i].len;) { + for (bit = 0 ; bit < 8 && j < tests[i].len; ++bit, ++j) { + set_bit(&dest[j / 8], bit, tests[i].src[j] == '0' ? 0 : 1); + } + } + for (j = 0 ; j < bytes; ++j) { + g_assert(dest[j] == (guchar) tests[i].dest[j]); + } + g_free(dest); + } +} + +static void test_mono_edge_highlight(void) +{ + unsigned int i; + int j, bit; + guint8 *and; + guint8 *xor; + guint8 *dest; + guint8 *dest_correct; + int size, pixels; + + test_set_bit(); + + for (i = 0 ; i < G_N_ELEMENTS(mono); ++i) { + pixels = mono[i].width * mono[i].height; + size = (pixels + 7) / 8; + and = g_malloc0(size); + xor = g_malloc0(size); + dest = g_malloc0(pixels * 4); + dest_correct = g_malloc(pixels * 4); + for (j = 0 ; j < pixels;) { + for (bit = 0; bit < 8 && j < pixels; ++bit, ++j) { + set_bit(&and[j / 8], bit, mono[i].and[j] == '0' ? 0 : 1); + set_bit(&xor[j / 8], bit, mono[i].xor[j] == '0' ? 0 : 1); + } + } + for (j = 0 ; j < pixels * 4 ; ++j) { + dest_correct[j] = mono[i].dest[j] == '0' ? 0x00 : 0xff; + } + spice_mono_edge_highlight(mono[i].width, mono[i].height, and, xor, dest); + for (j = 0; j < pixels; ++j) { + g_assert(dest[j] == dest_correct[j]); + } + g_free(and); + g_free(xor); + g_free(dest); + g_free(dest_correct); + } +} + +int main(int argc, char* argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/util/dos2unix", test_dos2unix); + g_test_add_func("/util/unix2dos", test_unix2dos); + g_test_add_func("/util/mono_edge_highlight", test_mono_edge_highlight); + + return g_test_run (); +} diff --git a/vapi/Makefile.am b/vapi/Makefile.am new file mode 100644 index 0000000..aaab848 --- /dev/null +++ b/vapi/Makefile.am @@ -0,0 +1,40 @@ +NULL = +CLEANFILES = + +vapidir = $(datadir)/vala/vapi +vapi_DATA = \ + spice-client-glib-2.0.vapi \ + $(NULL) +dist_vapi_DATA = \ + spice-client-glib-2.0.deps \ + $(NULL) + +if WITH_GTK +vapi_DATA += spice-client-gtk-3.0.vapi +dist_vapi_DATA += spice-client-gtk-3.0.deps +endif + +EXTRA_DIST = \ + spice-client-gtk-3.0.deps \ + SpiceClientGLib-2.0.metadata \ + $(NULL) + +CLEANFILES += $(vapi_DATA) + +spice-client-glib-2.0.vapi: $(top_builddir)/src/SpiceClientGLib-2.0.gir SpiceClientGLib-2.0.metadata + $(AM_V_GEN)$(VAPIGEN) -q \ + --metadatadir=$(srcdir) \ + --library spice-client-glib-2.0 \ + --pkg gio-2.0 \ + $< + +spice-client-gtk-3.0.vapi: $(top_builddir)/src/SpiceClientGtk-3.0.gir spice-client-glib-2.0.vapi + $(AM_V_GEN)$(VAPIGEN) -q \ + --vapidir=$(builddir) \ + --girdir=$(top_builddir)/src \ + --pkg spice-client-glib-2.0 \ + --pkg gtk+-3.0 \ + --library spice-client-gtk-3.0 \ + $< + +-include $(top_srcdir)/git.mk diff --git a/vapi/Makefile.in b/vapi/Makefile.in new file mode 100644 index 0000000..a2590d5 --- /dev/null +++ b/vapi/Makefile.in @@ -0,0 +1,670 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_GTK_TRUE@am__append_1 = spice-client-gtk-3.0.vapi +@WITH_GTK_TRUE@am__append_2 = spice-client-gtk-3.0.deps +subdir = vapi +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/ld-version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/spice-compile-warnings.m4 \ + $(top_srcdir)/m4/warnings.m4 \ + $(top_srcdir)/spice-common/m4/spice-deps.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_vapi_DATA_DIST) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__dist_vapi_DATA_DIST = spice-client-glib-2.0.deps \ + spice-client-gtk-3.0.deps +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(vapidir)" "$(DESTDIR)$(vapidir)" +DATA = $(dist_vapi_DATA) $(vapi_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_HELPER_DIR = @ACL_HELPER_DIR@ +ACL_LIBS = @ACL_LIBS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT2_CFLAGS = @GOBJECT2_CFLAGS@ +GOBJECT2_LIBS = @GOBJECT2_LIBS@ +GREP = @GREP@ +GSTAUDIO_CFLAGS = @GSTAUDIO_CFLAGS@ +GSTAUDIO_LIBS = @GSTAUDIO_LIBS@ +GSTVIDEO_CFLAGS = @GSTVIDEO_CFLAGS@ +GSTVIDEO_LIBS = @GSTVIDEO_LIBS@ +GST_INSPECT_1_0 = @GST_INSPECT_1_0@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_REQUIRED = @GTK_REQUIRED@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUSB_HOTPLUG_CFLAGS = @LIBUSB_HOTPLUG_CFLAGS@ +LIBUSB_HOTPLUG_LIBS = @LIBUSB_HOTPLUG_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LZ4_CFLAGS = @LZ4_CFLAGS@ +LZ4_LIBS = @LZ4_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PHODAV_CFLAGS = @PHODAV_CFLAGS@ +PHODAV_LIBS = @PHODAV_LIBS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNP_IDS = @PNP_IDS@ +POFILES = @POFILES@ +POLICYDIR = @POLICYDIR@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +RANLIB = @RANLIB@ +SASL_CFLAGS = @SASL_CFLAGS@ +SASL_LIBS = @SASL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SMARTCARD_CFLAGS = @SMARTCARD_CFLAGS@ +SMARTCARD_LIBS = @SMARTCARD_LIBS@ +SPICE_CFLAGS = @SPICE_CFLAGS@ +SPICE_GLIB_CFLAGS = @SPICE_GLIB_CFLAGS@ +SPICE_GLIB_REQUIRES = @SPICE_GLIB_REQUIRES@ +SPICE_GTK_CFLAGS = @SPICE_GTK_CFLAGS@ +SPICE_GTK_LOCALEDIR = @SPICE_GTK_LOCALEDIR@ +SPICE_GTK_MAJOR_VERSION = @SPICE_GTK_MAJOR_VERSION@ +SPICE_GTK_MICRO_VERSION = @SPICE_GTK_MICRO_VERSION@ +SPICE_GTK_MINOR_VERSION = @SPICE_GTK_MINOR_VERSION@ +SPICE_GTK_REQUIRES = @SPICE_GTK_REQUIRES@ +SPICE_PROTOCOL_CFLAGS = @SPICE_PROTOCOL_CFLAGS@ +SPICE_PROTOCOL_LIBS = @SPICE_PROTOCOL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STOW = @STOW@ +STRIP = @STRIP@ +USBREDIR_CFLAGS = @USBREDIR_CFLAGS@ +USBREDIR_LIBS = @USBREDIR_LIBS@ +USB_IDS = @USB_IDS@ +USE_NLS = @USE_NLS@ +VALAC = @VALAC@ +VAPIDIR = @VAPIDIR@ +VAPIGEN = @VAPIGEN@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_LDFLAGS = @WARN_LDFLAGS@ +WARN_PYFLAGS = @WARN_PYFLAGS@ +XGETTEXT = @XGETTEXT@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +CLEANFILES = $(vapi_DATA) +vapidir = $(datadir)/vala/vapi +vapi_DATA = spice-client-glib-2.0.vapi $(NULL) $(am__append_1) +dist_vapi_DATA = spice-client-glib-2.0.deps $(NULL) $(am__append_2) +EXTRA_DIST = \ + spice-client-gtk-3.0.deps \ + SpiceClientGLib-2.0.metadata \ + $(NULL) + +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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign vapi/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign vapi/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_vapiDATA: $(dist_vapi_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_vapi_DATA)'; test -n "$(vapidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(vapidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(vapidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(vapidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(vapidir)" || exit $$?; \ + done + +uninstall-dist_vapiDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_vapi_DATA)'; test -n "$(vapidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(vapidir)'; $(am__uninstall_files_from_dir) +install-vapiDATA: $(vapi_DATA) + @$(NORMAL_INSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(vapidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(vapidir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(vapidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(vapidir)" || exit $$?; \ + done + +uninstall-vapiDATA: + @$(NORMAL_UNINSTALL) + @list='$(vapi_DATA)'; test -n "$(vapidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(vapidir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(vapidir)" "$(DESTDIR)$(vapidir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_vapiDATA install-vapiDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -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_vapiDATA uninstall-vapiDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am 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_vapiDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip install-vapiDATA \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-dist_vapiDATA uninstall-vapiDATA + +.PRECIOUS: Makefile + + +spice-client-glib-2.0.vapi: $(top_builddir)/src/SpiceClientGLib-2.0.gir SpiceClientGLib-2.0.metadata + $(AM_V_GEN)$(VAPIGEN) -q \ + --metadatadir=$(srcdir) \ + --library spice-client-glib-2.0 \ + --pkg gio-2.0 \ + $< + +spice-client-gtk-3.0.vapi: $(top_builddir)/src/SpiceClientGtk-3.0.gir spice-client-glib-2.0.vapi + $(AM_V_GEN)$(VAPIGEN) -q \ + --vapidir=$(builddir) \ + --girdir=$(top_builddir)/src \ + --pkg spice-client-glib-2.0 \ + --pkg gtk+-3.0 \ + --library spice-client-gtk-3.0 \ + $< + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/vapi/SpiceClientGLib-2.0.metadata b/vapi/SpiceClientGLib-2.0.metadata new file mode 100644 index 0000000..acb7f57 --- /dev/null +++ b/vapi/SpiceClientGLib-2.0.metadata @@ -0,0 +1 @@ +Channel.open_fd#virtual_method skip diff --git a/vapi/spice-client-glib-2.0.deps b/vapi/spice-client-glib-2.0.deps new file mode 100644 index 0000000..cd10dfd --- /dev/null +++ b/vapi/spice-client-glib-2.0.deps @@ -0,0 +1 @@ +gio-2.0 diff --git a/vapi/spice-client-gtk-3.0.deps b/vapi/spice-client-gtk-3.0.deps new file mode 100644 index 0000000..d04a10b --- /dev/null +++ b/vapi/spice-client-gtk-3.0.deps @@ -0,0 +1,2 @@ +spice-client-glib-2.0 +gtk+-3.0 -- 2.30.2